[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