[PATCH] Cilk Keywords (_Cilk_spawn and _Cilk_sync) for C

Aldy Hernandez aldyh@redhat.com
Fri Aug 9 10:40:00 GMT 2013



>>> --- gcc/expr.c
>>> +++ gcc/expr.c
>>> @@ -9569,6 +9569,21 @@ expand_expr_real_1 (tree exp, rtx target, enum
>> machine_mode tmode,
>>>   	}
>>>
>>>         return expand_constructor (exp, target, modifier, false);
>>> +    case INDIRECT_REF:
>>> +      {
>>> +	tree exp1 = TREE_OPERAND (exp, 0);
>>> +	if (modifier != EXPAND_WRITE)
>>> +	  {
>>> +	    tree t = fold_read_from_constant_string (exp);
>>> +	    if (t)
>>> +	      return expand_expr (t, target, tmode, modifier);
>>> +	  }
>>> +	op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
>>> +	op0 = memory_address (mode, op0);
>>> +	temp = gen_rtx_MEM (mode, op0);
>>> +	set_mem_attributes (temp, exp, 0);
>>> +	return temp;
>>> +      }
>>
>> Ughhh, what's the rationale for this?  Are generic changes to
>> expand_expr really needed?
>
> Yes, I am expanding some variables of type "ptr->value" and those are emitted as INDIRECT_REF.

The fact that you are getting an INDIRECT_REF this late in the game is 
suspect.

Are you building with ENABLE_CHECKING, because it seems this should have 
been caught.  See the places in tree-cfg.c with this:

     case INDIRECT_REF:
       error ("INDIRECT_REF in gimple IL");
       return t;
>
>>
>>> +  /* During LTO, the is_cilk_function flag gets cleared.
>>> +     If __cilkrts_pop_frame is called, then this definitely must be a
>>> +     cilk function.  */
>>> +  if (cfun)
>>> +    cfun->is_cilk_function = 1;
>>
>> I don't know much about our LTO implementation, but perhaps you need to
>> teach LTO to stream this bit in/out?  And of course, an accompanying LTO
>> test to check for this problem you're encountering would be appropriate.
>>
>
> I also have a limited knowledge of LTO. This seem to be the most straightforward way of doing it (atleast for me).

See how other bits in `struct function' are streamed in/out in LTO, for 
example in output_struct_function_base()

   bp_pack_value (&bp, fn->calls_alloca, 1);
   bp_pack_value (&bp, fn->calls_setjmp, 1);
   bp_pack_value (&bp, fn->va_list_fpr_size, 8);
   bp_pack_value (&bp, fn->va_list_gpr_size, 8);

and the corresponding in input_struct_function_base():

   fn->calls_alloca = bp_unpack_value (&bp, 1);
   fn->calls_setjmp = bp_unpack_value (&bp, 1);
   fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
   fn->va_list_gpr_size = bp_unpack_value (&bp, 8);

Also, you will need a testcase to make sure later changes to the 
compiler do not break LTO wrt Cilk features you have added.

>
>>> +       /* We need frame pointer for all Cilk Plus functions that uses
>>> +	  Cilk Keywords.  */
>>> +       || (flag_enable_cilkplus && cfun->is_cilk_function)
>>
>> "need a frame pointer"
>>
>> "that use"
>>
>> s/Keywords/keywords/
>>
>
> It should be keywords, because you need frame-pointer for "_Cilk_spawn and _Cilk_sync" and "_Cilk_for"

I meant that you should lowercase the "K".

>
>>> +  /* This variable will tell whether we are on a spawn helper or not */
>>> +  unsigned int is_cilk_helper_function : 1;
>>
>> Where is this used?
>>
>
> Well, it is not used now but later on when I add Tools support it will be. I will remove it for now.

Yes, please.

>>> --- gcc/ipa-inline-analysis.c
>>> +++ gcc/ipa-inline-analysis.c
>>> @@ -1433,6 +1433,9 @@ initialize_inline_failed (struct cgraph_edge *e)
>>>       e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
>>>     else if (e->call_stmt_cannot_inline_p)
>>>       e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
>>> +  else if (flag_enable_cilkplus && cfun && cfun->calls_spawn)
>>> +    /* We can't inline if the function is spawing a function.  */
>>> +    e->inline_failed = CIF_BODY_NOT_AVAILABLE;
>>
>> Hmmm, if we don't have a cfun, perhaps we should be sticking this
>> calls_spawn bit in the cgraph node.
>>
>> Richard?  Anyone?
>>
>
> When I am first setting this, I don't think cgraph is available.

See Richard's comment with regards to struct function and its 
availability via the callee edge.  Also see his comment regarding the 
inappropriate error message.

>>> @@ -3496,7 +3510,7 @@ struct GTY(()) tree_function_decl {
>>>        ???  The bitfield needs to be able to hold all target function
>>>   	  codes as well.  */
>>>     ENUM_BITFIELD(built_in_function) function_code : 11;
>>> -  ENUM_BITFIELD(built_in_class) built_in_class : 2;
>>> +  ENUM_BITFIELD(built_in_class) built_in_class  ;
>>
>> What's this for?
>>
>
> Added a new enum field called BUILT_IN_CILK so we need 3 bits instead of 2, since there are 5 fields instead of 4.

Hmm, yeah.  I see you added another field here:

> diff --git a/gcc/tree.h b/gcc/tree.h
> index 0058a4b..952362f 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -262,6 +262,7 @@ enum built_in_class
>    NOT_BUILT_IN = 0,
>    BUILT_IN_FRONTEND,
>    BUILT_IN_MD,
> +  BUILT_IN_CILK,
>    BUILT_IN_NORMAL
>  };

If you look at the comment above enum built_in_class, you will see that 
these classes specify which part of the compiler created the built-in 
(the frontend, the backend (MD), or a normal builtin).  I don't see how 
Cilk should be treated specially.  And even so, I don't see how you use 
this BUILT_IN_CILK class anywhere.

>>> +  if (DECL_BUILT_IN_CLASS (exp) == BUILT_IN_NORMAL)
>>> +    return DECL_FUNCTION_CODE (exp) == BUILT_IN_MEMCPY;
>>> +  return lang_hooks.cilkplus.spawnable_constructor (exp);
>>> +  return false;
>>
>
> That would be necessary for C++, but it returns false for C. So, should I take out this hook for now? Would prefer to keep it in

You can keep the hook, but do put a comment specifying that it's a place 
holder for C++.  And also, please remove the second return.

>> Are these two hooks ever set to anything but hook_bool_tree_false?  If
>> so, why the need for them?
>>
>
> Used in C++ but not in C.

Leave them.  Similar comment please.

>>> +     struct __cilkrts_worker {
>>> +       __cilkrts_stack_frame *volatile *volatile tail;
>>> +       __cilkrts_stack_frame *volatile *volatile head;
>>> +       __cilkrts_stack_frame *volatile *volatile exc;
>>> +       __cilkrts_stack_frame *volatile *volatile protected_tail;
>>> +       __cilkrts_stack_frame *volatile *ltq_limit;
>>
>> What's this "*volatile *volatile" stuff?
>>
>
> That is how the field is described in Cilk Runtime source (please see: http://gcc.gnu.org/svn/gcc/branches/cilkplus/libcilkrts/include/internal/abi.h)

Ok, I'm not a language expert, I presume this is specifying volatile on 
both indirections and is proper form.

>>> +/* Gimplifies the cilk_sync expression passed in *EXPR_P.  Returns
>> GS_ALL_DONE
>>> +   when finished.  */
>>> +
>>> +int
>>> +gimplify_cilk_sync (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p
>>> +		    ATTRIBUTE_UNUSED)
>>> +{
>>> +  tree sync_expr = build_cilk_sync ();
>>> +  *expr_p = NULL_TREE;
>>> +  gimplify_and_add (sync_expr, pre_p);
>>> +  return GS_ALL_DONE;
>>
>> I'm not a big fan of functions that always return the same thing.  The
>> caller should set GS_ALL_DONE accordingly.
>>
>
> The reason why I did this is that, there is a generic empty hook for this in langhooks.c that returns int. So, to reduce the number of code addition, I just made it return int. Also in future, if i want to add more things, having a return value I thought would be helpful.

Use void.  Set GS_ALL_DONE in the caller.  You can add the return value 
when you use it in the future.

Aldy



More information about the Gcc-patches mailing list