diff mbox

Merging Cilk Plus into Trunk (Patch 1 of approximately 22)

Message ID BF230D13CA30DD48930C31D40993300016C795F1@FMSMSX102.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V Sept. 9, 2012, 6:02 p.m. UTC
Hello Joseph,
	Here is an updated patch. I think I have fixed all the changes you and others have mentioned. Please let me know if everything looks OK. Thanks again for doing the review!

Sincerely,

Balaji V. Iyer.

Here are the fixed ChangeLog entries:

============================================================================================
gcc/ChangeLog
2012-09-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * attribs.c (is_elem_fn_attribute_p): New function.
        (decl_attributes): Added a check for Elemental function attribute when
        Cilk Plus is enabled.
        * cgraphunit.c (cgraph_decide_is_function_needed): Added a check for
        cloned elemental function when Cilk Plus is enabled.
        (cgraph_add_new_function): When Cilk Plus is enabled we call
        cgraph_get_create_node.
        (cgraph_analyze_functions): Added a check if the function call is a
        cloned elemental function when Cilk Plus is enabled.
        * cilkplus.h: New file.
        * elem-function-common.c: Likewise.
        * config/i386/i386.c (ix86_cilkplus_map_proc_to_attr): New function.
        (TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR): New define.
        * expr.c (expand_expr_real_1): Added a check if Cilk Plus is enabled.
        * function.h (struct function): Added elem_fn_already_cloned field.
        * gimplify.c (gimplify_function_tree): Added a check if Cilk Plus is
        enabled and if the function is an elemental function.  If so, then call
        the function to clone elemental function.
        * langhooks.c (lhd_elem_fn_create_fn): New function.
        * langhooks-def.h (LANG_HOOKS_CILKPLUS): New define.
        (LANG_HOOK_DECLS): Added LANG_HOOKS_CILKPLUS field.
        * langhooks.h (struct lang_hooks_for_cilkplus): New struct.
        (struct lang_hooks): Added a field called cilkplus.
        * target.def (TARGET_CILKPLUS): New hook vector.
        (builtin_map_processor_to_attr): New target hook def.
        * targhooks.c (default_builtin_map_processor_to_attr): New function.
        * doc/tm.texi: Regenerated.
        * doc/tm.texi.in (TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR): Documented
        new hook.
        * tree.h (tree_function_decl): Added a new field called
        elem_fn_already_cloned.
        (DECL_ELEM_FN_ALREADY_CLONED): New define.
        * tree-data-ref.c (find_data_references_in_stmt): Added a check for
        an elemental function call when Cilk Plus is enabled.
        * tree-inline.c (elem_fn_copy_arguments_for_versioning): New function.
        (initialize_elem_fn_cfun): Likewise.
        (tree_elem_fn_versioning): Likewise.
        * tree-vect-stmts.c (vect_get_vec_def_for_operand): Check parm type for
        an elemental function when Cilk Plus is enabled and set data definition
        accordingly.
        (elem_fn_vect_get_vec_def_for_operand): New function.
        (vect_finish_stmt_generation): Added a check for elemental function.
        (vectorizable_function): Check if the function call is a Cilk Plus
        elemental function.  If so, then insert the appopriate mangled name.
        (vectorizable_call): Eliminate the argument requirement when Cilk Plus
        is enabled for vectorization.  Also, set thee appropriate data def. for
        an elemental function call.
        (elem_fn_linear_init_vector): New function.
        * tree.c (build_elem_fn_linear_vector): Likewise.

gcc/c-family/ChangeLog
2012-09-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * c-common.c (struct c_common_attribute_table): Added vector
        attribute for Cilk Plus elemental function.
        (handle_vector_atribute): New function.
        * c-cpp-elem-function.c: New file.
        * c.opt (-fcilkplus): Added new flag.

gcc/c/ChangeLog
2012-09-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * c-decl.c (bind): Added a check for non NULL scope.
        * c-parser.c (c_parser_declaration_or_fndef): Added a check if Cilk
        Plus defined.  If so, then we save the arguments for a function
        declaration.
        (c_parser_attributes): Added a check if Cilk Plus is enabled and if
        elemental function vector attribute is given.  If so, then call the
        function c_parser_elem_fn_expr_list ().
        (c_parser_elem_fn_processor_clause): New function.
        (c_parser_elem_fn_uniform_clause): Likewise.
        (c_parser_elem_fn_linear_clause): Likewise.
        (c_parser_elem_fn_vlength_clause): Likewise.
        (c_parser_elem_fn_expr_list): Likewise.

===========================================================================================


>-----Original Message-----
>From: Joseph Myers [mailto:joseph@codesourcery.com]
>Sent: Thursday, September 06, 2012 12:18 PM
>To: Iyer, Balaji V
>Cc: gcc-patches@gcc.gnu.org; Aldy Hernandez (aldyh@redhat.com); Jeff Law;
>rth@redhat.com
>Subject: RE: [PATCH] Merging Cilk Plus into Trunk (Patch 1 of approximately 22)
>
>On Thu, 6 Sep 2012, Iyer, Balaji V wrote:
>
>> Ok, I was mistaken there. I thought we had to add a changelog entry
>> for every function and not every file. I will fix it in the updated
>> patch I send soon.
>
>For functions in existing files you do need to mention each function - but not for
>new files.
>
>> >create_processor_attribute contains hardcoded references to
>> >x86-specific functionality.  This is not OK; all such target
>> >dependencies need to be kept within the back ends, and handled from
>> >the rest of the compiler via target hooks (in most cases, new target
>dependencies must use target hooks not target macros).
>>
>> The only thing I am doing in that function is to add appropriate
>> attribute. In elemental function, there is a processor clause that
>> will allow users to set the type of processor they want the function
>> compiled for. All I am doing is to map that information to the appropriate
>"arch"
>> attribute. I didn't think it had any back end pecularity.
>
>Concepts such as "pentium_4" are architecture-specific and have no place in
>front-end files.  This whole mapping from one sort of string to another belongs
>within the back end.
>
>--
>Joseph S. Myers
>joseph@codesourcery.com

Comments

Richard Biener Sept. 10, 2012, 10:08 a.m. UTC | #1
On Sun, Sep 9, 2012 at 8:02 PM, Iyer, Balaji V <balaji.v.iyer@intel.com> wrote:
> Hello Joseph,
>         Here is an updated patch. I think I have fixed all the changes you and others have mentioned. Please let me know if everything looks OK. Thanks again for doing the review!

The ChangeLog still mentions the vectorizer looking at flag_cilk_plus.  Also
this patch does not contain a single testcase and thus all codepaths are
not exercised when bootstrapping and testing.

You do not mention how this feature works from an ABI perspective.

I don't think this is anywere ready to go in.  Please split it into
two parts at least,
part one would be to make the vectorizer support vectorizing functions with
the "elemental function" attribute by assuming a vectorized variant with
documented mangling exists.  That feature should work regardless of whether
Cilk+ is enabled or not.  The mangling needs to be documented alongside
the documentation for the "elemental funciton" attribute.  Part two would be
the rest, possibly re-implemented in the way that was suggested.

Thanks,
Richard.

> Sincerely,
>
> Balaji V. Iyer.
>
> Here are the fixed ChangeLog entries:
>
> ============================================================================================
> gcc/ChangeLog
> 2012-09-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>
>         * attribs.c (is_elem_fn_attribute_p): New function.
>         (decl_attributes): Added a check for Elemental function attribute when
>         Cilk Plus is enabled.
>         * cgraphunit.c (cgraph_decide_is_function_needed): Added a check for
>         cloned elemental function when Cilk Plus is enabled.
>         (cgraph_add_new_function): When Cilk Plus is enabled we call
>         cgraph_get_create_node.
>         (cgraph_analyze_functions): Added a check if the function call is a
>         cloned elemental function when Cilk Plus is enabled.
>         * cilkplus.h: New file.
>         * elem-function-common.c: Likewise.
>         * config/i386/i386.c (ix86_cilkplus_map_proc_to_attr): New function.
>         (TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR): New define.
>         * expr.c (expand_expr_real_1): Added a check if Cilk Plus is enabled.
>         * function.h (struct function): Added elem_fn_already_cloned field.
>         * gimplify.c (gimplify_function_tree): Added a check if Cilk Plus is
>         enabled and if the function is an elemental function.  If so, then call
>         the function to clone elemental function.
>         * langhooks.c (lhd_elem_fn_create_fn): New function.
>         * langhooks-def.h (LANG_HOOKS_CILKPLUS): New define.
>         (LANG_HOOK_DECLS): Added LANG_HOOKS_CILKPLUS field.
>         * langhooks.h (struct lang_hooks_for_cilkplus): New struct.
>         (struct lang_hooks): Added a field called cilkplus.
>         * target.def (TARGET_CILKPLUS): New hook vector.
>         (builtin_map_processor_to_attr): New target hook def.
>         * targhooks.c (default_builtin_map_processor_to_attr): New function.
>         * doc/tm.texi: Regenerated.
>         * doc/tm.texi.in (TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR): Documented
>         new hook.
>         * tree.h (tree_function_decl): Added a new field called
>         elem_fn_already_cloned.
>         (DECL_ELEM_FN_ALREADY_CLONED): New define.
>         * tree-data-ref.c (find_data_references_in_stmt): Added a check for
>         an elemental function call when Cilk Plus is enabled.
>         * tree-inline.c (elem_fn_copy_arguments_for_versioning): New function.
>         (initialize_elem_fn_cfun): Likewise.
>         (tree_elem_fn_versioning): Likewise.
>         * tree-vect-stmts.c (vect_get_vec_def_for_operand): Check parm type for
>         an elemental function when Cilk Plus is enabled and set data definition
>         accordingly.
>         (elem_fn_vect_get_vec_def_for_operand): New function.
>         (vect_finish_stmt_generation): Added a check for elemental function.
>         (vectorizable_function): Check if the function call is a Cilk Plus
>         elemental function.  If so, then insert the appopriate mangled name.
>         (vectorizable_call): Eliminate the argument requirement when Cilk Plus
>         is enabled for vectorization.  Also, set thee appropriate data def. for
>         an elemental function call.
>         (elem_fn_linear_init_vector): New function.
>         * tree.c (build_elem_fn_linear_vector): Likewise.
>
> gcc/c-family/ChangeLog
> 2012-09-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>
>         * c-common.c (struct c_common_attribute_table): Added vector
>         attribute for Cilk Plus elemental function.
>         (handle_vector_atribute): New function.
>         * c-cpp-elem-function.c: New file.
>         * c.opt (-fcilkplus): Added new flag.
>
> gcc/c/ChangeLog
> 2012-09-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>
>
>         * c-decl.c (bind): Added a check for non NULL scope.
>         * c-parser.c (c_parser_declaration_or_fndef): Added a check if Cilk
>         Plus defined.  If so, then we save the arguments for a function
>         declaration.
>         (c_parser_attributes): Added a check if Cilk Plus is enabled and if
>         elemental function vector attribute is given.  If so, then call the
>         function c_parser_elem_fn_expr_list ().
>         (c_parser_elem_fn_processor_clause): New function.
>         (c_parser_elem_fn_uniform_clause): Likewise.
>         (c_parser_elem_fn_linear_clause): Likewise.
>         (c_parser_elem_fn_vlength_clause): Likewise.
>         (c_parser_elem_fn_expr_list): Likewise.
>
> ===========================================================================================
>
>
>>-----Original Message-----
>>From: Joseph Myers [mailto:joseph@codesourcery.com]
>>Sent: Thursday, September 06, 2012 12:18 PM
>>To: Iyer, Balaji V
>>Cc: gcc-patches@gcc.gnu.org; Aldy Hernandez (aldyh@redhat.com); Jeff Law;
>>rth@redhat.com
>>Subject: RE: [PATCH] Merging Cilk Plus into Trunk (Patch 1 of approximately 22)
>>
>>On Thu, 6 Sep 2012, Iyer, Balaji V wrote:
>>
>>> Ok, I was mistaken there. I thought we had to add a changelog entry
>>> for every function and not every file. I will fix it in the updated
>>> patch I send soon.
>>
>>For functions in existing files you do need to mention each function - but not for
>>new files.
>>
>>> >create_processor_attribute contains hardcoded references to
>>> >x86-specific functionality.  This is not OK; all such target
>>> >dependencies need to be kept within the back ends, and handled from
>>> >the rest of the compiler via target hooks (in most cases, new target
>>dependencies must use target hooks not target macros).
>>>
>>> The only thing I am doing in that function is to add appropriate
>>> attribute. In elemental function, there is a processor clause that
>>> will allow users to set the type of processor they want the function
>>> compiled for. All I am doing is to map that information to the appropriate
>>"arch"
>>> attribute. I didn't think it had any back end pecularity.
>>
>>Concepts such as "pentium_4" are architecture-specific and have no place in
>>front-end files.  This whole mapping from one sort of string to another belongs
>>within the back end.
>>
>>--
>>Joseph S. Myers
>>joseph@codesourcery.com
Joseph Myers Sept. 10, 2012, 11:23 a.m. UTC | #2
On Sun, 9 Sep 2012, Iyer, Balaji V wrote:

> 	Here is an updated patch. I think I have fixed all the changes you 
> and others have mentioned. Please let me know if everything looks OK. 
> Thanks again for doing the review!

Has the user documentation for this feature been posted?  For patch review 
we really need a self-contained submission that for any feature 
implemented includes not just the implementation but the testcases and the 
documentation.  I think the testsuite patch also needs reworking to make 
it easy to add support for new architectures.

I think you need to revisit your split into 22 patches and arrange things 
based primarily on features.  If the changes for a feature are so big they 
can't be posted in one message, you should still always post all the 
patches for that feature together (implementation, documentation, 
testcases) - even if not all parts have changed in a particular revision.
Iyer, Balaji V Sept. 10, 2012, 12:40 p.m. UTC | #3
>-----Original Message-----
>From: Joseph Myers [mailto:joseph@codesourcery.com]
>Sent: Monday, September 10, 2012 7:23 AM
>To: Iyer, Balaji V
>Cc: gcc-patches@gcc.gnu.org; Aldy Hernandez (aldyh@redhat.com); Jeff Law;
>rth@redhat.com
>Subject: RE: [PATCH] Merging Cilk Plus into Trunk (Patch 1 of approximately 22)
>
>On Sun, 9 Sep 2012, Iyer, Balaji V wrote:
>
>> 	Here is an updated patch. I think I have fixed all the changes you
>> and others have mentioned. Please let me know if everything looks OK.
>> Thanks again for doing the review!
>
>Has the user documentation for this feature been posted?  For patch review we
>really need a self-contained submission that for any feature implemented
>includes not just the implementation but the testcases and the documentation.  I
>think the testsuite patch also needs reworking to make it easy to add support for
>new architectures.

I think you had some changes for the test cases and I am currently working on it. 

>
>I think you need to revisit your split into 22 patches and arrange things based
>primarily on features.  If the changes for a feature are so big they can't be posted
>in one message, you should still always post all the patches for that feature
>together (implementation, documentation,
>testcases) - even if not all parts have changed in a particular revision.

So, I assume it is OK for me to include testsuites with the code-changes? I included them separately because I remember someone in the mailing list saying the patch size must be small and one logical way is to put test cases separately from the code-changes.

>
>--
>Joseph S. Myers
>joseph@codesourcery.com
Joseph Myers Sept. 10, 2012, 3:12 p.m. UTC | #4
On Mon, 10 Sep 2012, Iyer, Balaji V wrote:

> So, I assume it is OK for me to include testsuites with the 
> code-changes? I included them separately because I remember someone in 
> the mailing list saying the patch size must be small and one logical way 
> is to put test cases separately from the code-changes.

I believe the message size limit for gcc-patches is 400 kB, and this patch 
is way below that.  But if the self-contained unit of changes exceeds 400 
kB, you should still post the whole thing at once in multiple messages so 
that a matched set of patches that could go in together is available for 
review.
diff mbox

Patch

diff --git gcc/Makefile.in gcc/Makefile.in
index 9886b6c..e5ef1e4 100644
--- gcc/Makefile.in
+++ gcc/Makefile.in
@@ -1114,7 +1114,8 @@  C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
   c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \
   c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
   c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
-  c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o
+  c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o \
+  c-family/c-cpp-elem-function.o
 
 # Language-independent object files.
 # We put the insn-*.o files first so that a parallel make will build
@@ -1190,6 +1191,7 @@  OBJS = \
 	dwarf2cfi.o \
 	dwarf2out.o \
 	ebitmap.o \
+	elem-function-common.o \
 	emit-rtl.o \
 	et-forest.o \
 	except.o \
@@ -1975,7 +1977,7 @@  default-c.o: config/default-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 
 attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
 	$(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) \
-	$(TARGET_H) langhooks.h $(CPPLIB_H) $(PLUGIN_H)
+	$(TARGET_H) langhooks.h $(CPPLIB_H) $(PLUGIN_H) cilkplus.h
 
 incpath.o: incpath.c incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
 		intl.h prefix.h coretypes.h $(TM_H) cppdefault.h $(TARGET_H) \
@@ -2502,7 +2504,7 @@  tree-scalar-evolution.o : tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
    $(PARAMS_H) gt-tree-scalar-evolution.h
 tree-data-ref.o : tree-data-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
    $(GIMPLE_PRETTY_PRINT_H) $(TREE_FLOW_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
-   langhooks.h tree-affine.h $(PARAMS_H)
+   langhooks.h tree-affine.h $(PARAMS_H) cilkplus.h
 sese.o : sese.c sese.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_PRETTY_PRINT_H) \
    $(TREE_FLOW_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(TREE_PASS_H) value-prof.h
 graphite.o : graphite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DIAGNOSTIC_CORE_H) \
@@ -2559,7 +2561,7 @@  tree-vect-stmts.o: tree-vect-stmts.c $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h dumpfile.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) \
    $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(CFGLOOP_H) \
    $(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) \
-   langhooks.h $(GIMPLE_PRETTY_PRINT_H)
+   langhooks.h $(GIMPLE_PRETTY_PRINT_H) cilkplus.h
 tree-vect-data-refs.o: tree-vect-data-refs.c $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h dumpfile.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
    $(TREE_FLOW_H) $(CFGLOOP_H) \
@@ -3332,6 +3334,8 @@  lower-subreg.o : lower-subreg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) $(OBSTACK_H) $(BITMAP_H) \
    $(EXPR_H) $(EXCEPT_H) $(REGS_H) $(TREE_PASS_H) $(DF_H) dce.h \
    lower-subreg.h
+elem-function.o: elem-function.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
+   $(OPTABS_H) $(RECOG_H)
 target-globals.o : target-globals.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) insn-config.h $(MACHMODE_H) $(GGC_H) toplev.h target-globals.h \
    $(FLAGS_H) $(REGS_H) $(RTL_H) reload.h expmed.h $(EXPR_H) $(OPTABS_H) \
diff --git gcc/attribs.c gcc/attribs.c
index d3af414..7c8e037 100644
--- gcc/attribs.c
+++ gcc/attribs.c
@@ -33,6 +33,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "hashtab.h"
 #include "plugin.h"
+#include "cilkplus.h"
 
 /* Table of the tables of attributes (common, language, format, machine)
    searched.  */
@@ -102,6 +103,22 @@  eq_attr (const void *p, const void *q)
   return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]);
 }
 
+/* This will return true when name matches an elemental function mask.  */
+
+bool
+is_elem_fn_attribute_p (tree name)
+{
+  if (flag_enable_cilkplus)
+    return false;
+  return is_attribute_p ("mask", name)
+    || is_attribute_p ("unmask", name)
+    || is_attribute_p ("vectorlength", name)
+    || is_attribute_p ("vector", name)
+    || is_attribute_p ("linear", name)
+    || is_attribute_p ("uniform", name);
+}
+
+
 /* Initialize attribute tables, and make some sanity checks
    if --enable-checking.  */
 
@@ -312,6 +329,12 @@  decl_attributes (tree *node, tree attributes, int flags)
 
       if (spec == NULL)
 	{
+	  if (flag_enable_cilkplus && is_elem_fn_attribute_p (name))
+	    {
+	      returned_attrs = tree_cons (name, args, returned_attrs);
+	      DECL_ATTRIBUTES (*anode) = tree_cons (name, args,
+						    DECL_ATTRIBUTES (*anode));
+	    }
 	  if (!(flags & (int) ATTR_FLAG_BUILT_IN))
 	    warning (OPT_Wattributes, "%qE attribute directive ignored",
 		     name);
diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index 502613a..1a69623 100644
--- gcc/c-family/c-common.c
+++ gcc/c-family/c-common.c
@@ -45,6 +45,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "opts.h"
 #include "cgraph.h"
 #include "target-def.h"
+#include "cilkplus.h"
 
 cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 
@@ -372,6 +373,7 @@  static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
 static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
 static tree handle_target_attribute (tree *, tree, tree, int, bool *);
 static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
+static tree handle_vector_attribute (tree *, tree, tree, int, bool *);
 static tree ignore_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
@@ -726,6 +728,8 @@  const struct attribute_spec c_common_attribute_table[] =
 			      handle_target_attribute, false },
   { "optimize",               1, -1, true, false, false,
 			      handle_optimize_attribute, false },
+  { "vector",                 0, -1, true, false, false,
+                                  handle_vector_attribute, false },
   /* For internal use only.  The leading '*' both prevents its usage in
      source code and signals that it may be overridden by machine tables.  */
   { "*tm regparm",            0, 0, false, true, true,
@@ -8638,6 +8642,18 @@  parse_optimize_options (tree args, bool attr_p)
   return ret;
 }
 
+/* For handling the vector attribute that is used to indicate elemental
+   functions in Cilk Plus.  */
+
+static tree
+handle_vector_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
+			 tree args ATTRIBUTE_UNUSED,
+			 int ARG_UNUSED (flags), 
+			 bool *no_add_attrs ATTRIBUTE_UNUSED)
+{
+  return NULL_TREE;
+}
+
 /* For handling "optimize" attribute. arguments as in
    struct attribute_spec.handler.  */
 
diff --git gcc/c-family/c-cpp-elem-function.c gcc/c-family/c-cpp-elem-function.c
new file mode 100644
index 0000000..5cb642f
--- /dev/null
+++ gcc/c-family/c-cpp-elem-function.c
@@ -0,0 +1,471 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains C/C++ specific functions for elemental
+   functions.
+   
+   Copyright (C) 2012  Free Software Foundation, Inc.
+   Written by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+              Intel Corporation
+
+   Many Thanks to Karthik Kumar for advice on the basic technique
+   about cloning functions.
+   
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "cilkplus.h"
+#include "basic-block.h"
+#include "output.h"
+#include "c-family/c-common.h"
+#include "diagnostic.h"
+#include "tree-flow.h"
+#include "tree-dump.h"
+#include "tree-pass.h"
+#include "timevar.h"
+#include "flags.h"
+#include "c/c-tree.h"
+#include "tree-inline.h"
+#include "cgraph.h"
+#include "ipa-prop.h"
+#include "opts.h"
+#include "tree-iterator.h"
+#include "options.h"
+#include "intl.h"
+#include "vec.h"
+#include "target.h"
+
+static tree create_optimize_attribute (int);
+static tree create_processor_attribute (elem_fn_info *, tree *);
+static tree elem_fn_build_array (tree base_var, tree index);
+
+
+/* This function will create the appropriate __target__ attribute for the 
+   processor.  */
+
+static tree
+create_processor_attribute (elem_fn_info *elem_fn_values, tree *opposite_attr)
+{
+  if (elem_fn_values)
+    return targetm.cilkplus.builtin_map_processor_to_attr 
+      (elem_fn_values->proc_type, opposite_attr);
+  else
+    {
+      /* We should never get here.  If we get here, something wrong has
+	 happened, so we reset the whole proc. attribute.  */
+      *opposite_attr = NULL_TREE;
+      return NULL_TREE;
+    }
+}
+
+/* This will create an optimize attribute for the vector function, to make sure
+   the vectorizer is turned on and has its full capabilities.  */
+
+static tree
+create_optimize_attribute (int option)
+{
+  tree opt_attr;
+  VEC(tree,gc) *opt_vec = VEC_alloc (tree,gc, 4);
+  char optimization[2];
+  optimization[0] = 'O';
+  
+  if (option == 3)
+    optimization[1] = '3';
+  else if (option == 2)
+    optimization[1] = '2';
+  else if (option == 1)
+    optimization[1] = '1';
+  else if (option == 0)
+    optimization[1] = '0';
+  
+  VEC_safe_push (tree, gc, opt_vec, build_string (2, optimization));
+  opt_attr = build_tree_list_vec (opt_vec);
+  VEC_truncate (tree, opt_vec, 0);
+  opt_attr = build_tree_list (get_identifier ("optimize"), opt_attr);
+  return opt_attr;
+}
+
+
+/* This function will store return expression to a temporary var.  */
+
+static tree
+replace_return_with_new_var (tree *tp, int *walk_subtrees, void *data)
+{
+  tree mod_expr = NULL_TREE, return_var = NULL_TREE, ret_expr = NULL_TREE;
+  
+  if (!*tp)
+    return NULL_TREE;
+
+  if (TREE_CODE (*tp) == RETURN_EXPR)
+    {
+      return_var = (tree) data;
+      ret_expr = TREE_OPERAND (TREE_OPERAND (*tp, 0), 1);
+      mod_expr = build2 (MODIFY_EXPR, TREE_TYPE (return_var), return_var,
+			 ret_expr);
+      *tp = mod_expr;
+      *walk_subtrees = 0;
+    }
+  return NULL_TREE;
+}
+
+
+/* This function will create a vector access as a array access.  */
+
+static tree
+elem_fn_build_array (tree base_var, tree index)
+{
+  return build_array_ref (UNKNOWN_LOCATION, base_var, index);
+}
+
+/* This function wil replace all vector references with array references.  */
+
+static tree
+replace_array_ref_for_vec (tree *tp, int *walk_subtrees, void *data)
+{
+  tree ii_var;
+  fn_vect_elements *func_data;
+  if (!*tp)
+    return NULL_TREE;
+
+  if (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == PARM_DECL)
+    {
+      func_data = (fn_vect_elements *) data;
+      gcc_assert (func_data->induction_var);
+      for (ii_var = func_data->arguments; ii_var; ii_var = DECL_CHAIN (ii_var))
+	{
+	  if (DECL_NAME (ii_var) == DECL_NAME (*tp))
+	    {
+	      *tp =  elem_fn_build_array (*tp, func_data->induction_var);
+	      *walk_subtrees = 0;
+	      return NULL_TREE;
+	    }
+	}
+      if (func_data->return_var 
+	  && (DECL_NAME (*tp) == DECL_NAME (func_data->return_var)))
+	{
+	  *tp = elem_fn_build_array (*tp, func_data->induction_var);
+	  *walk_subtrees = 0;
+	}
+    }
+  return NULL_TREE;
+}
+
+/* This function will move return values to the end of the function.  */
+
+static void
+fix_elem_fn_return_value (tree fndecl, tree induction_var)
+{
+  fn_vect_elements data;
+  tree old_fndecl;
+  tree new_var, new_var_init,  new_body = NULL_TREE;
+  tree ret_expr, ret_stmt = NULL_TREE;
+  if (!fndecl || !DECL_SAVED_TREE (fndecl))
+    return;
+
+  if (TREE_TYPE (DECL_RESULT (fndecl)) == void_type_node)
+    return;
+
+  old_fndecl = current_function_decl;
+  push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+  current_function_decl = fndecl;
+  
+  new_var = create_tmp_var (TREE_TYPE (DECL_RESULT (fndecl)), "elem_fn_ret");
+  new_var_init =
+    build_vector_from_val
+    (TREE_TYPE (DECL_RESULT (fndecl)),
+     build_zero_cst (TREE_TYPE (TREE_TYPE (DECL_RESULT (fndecl)))));
+  DECL_INITIAL (new_var) = new_var_init;
+  walk_tree (&DECL_SAVED_TREE (fndecl), replace_return_with_new_var,
+	     (void *) new_var, NULL);
+  data.return_var = new_var;
+  data.arguments = DECL_ARGUMENTS (fndecl);
+  data.induction_var = induction_var;
+
+  walk_tree (&DECL_SAVED_TREE (fndecl), replace_array_ref_for_vec,
+	     (void *) &data, NULL);
+  ret_expr = build2 (MODIFY_EXPR, TREE_TYPE (new_var),
+		     DECL_RESULT (fndecl), new_var);
+  
+  ret_stmt = build1 (RETURN_EXPR, TREE_TYPE (ret_expr), ret_expr);
+  if (TREE_CODE (DECL_SAVED_TREE (fndecl)) == BIND_EXPR)
+    {
+      if (!BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl)))
+        ;
+      else if (TREE_CODE (BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl))) !=
+	       TREE_LIST)
+	{
+	  append_to_statement_list_force
+	    (BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl)), &new_body);
+	  append_to_statement_list_force (ret_stmt, &new_body);
+	}
+      else
+	{
+	  new_body = BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl));
+	  append_to_statement_list_force (ret_stmt, &new_body);
+	}
+      BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl)) = new_body;
+    }
+
+  pop_cfun ();
+  current_function_decl = old_fndecl;
+  return;
+}
+
+/* This function converts a vector value to scalar with a for loop in front.  */
+
+static tree
+add_elem_fn_loop (tree fndecl, int vlength)
+{
+  tree exit_label = NULL_TREE, if_label = NULL_TREE, body_label = NULL_TREE;
+  tree fn_body, loop = NULL_TREE, loop_var, mod_var, incr_expr, cond_expr;
+  tree cmp_expr, old_fndecl;
+  
+  if (!fndecl)
+    return NULL_TREE; 
+
+  if (!DECL_SAVED_TREE (fndecl))
+    return NULL_TREE;
+
+  old_fndecl = current_function_decl;
+  push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+  current_function_decl = fndecl;
+  
+  if (TREE_CODE (DECL_SAVED_TREE (fndecl)) == BIND_EXPR)
+    fn_body = BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl));
+  else
+    fn_body = DECL_SAVED_TREE (fndecl);
+
+  loop = alloc_stmt_list ();
+  
+  loop_var = create_tmp_var (integer_type_node, "ii_elem_fn_vec_val");
+  mod_var = build2 (MODIFY_EXPR, void_type_node, loop_var,
+		    build_int_cst (integer_type_node, 0));
+  append_to_statement_list_force (mod_var, &loop);
+  
+  if_label = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
+			 get_identifier ("if_lab"), void_type_node);
+  DECL_CONTEXT (if_label) = fndecl;
+  DECL_ARTIFICIAL (if_label) = 0;
+  DECL_IGNORED_P (if_label) = 1;
+
+  exit_label = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
+			   get_identifier ("exit_label"), void_type_node);
+  DECL_CONTEXT (exit_label) = fndecl;
+  DECL_ARTIFICIAL (exit_label) = 0;
+  DECL_IGNORED_P (exit_label) = 1;
+
+  body_label = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
+			   get_identifier ("body_label"), void_type_node);
+  DECL_CONTEXT (body_label) = fndecl;
+  DECL_ARTIFICIAL (body_label) = 0;
+  DECL_IGNORED_P (body_label) = 1;
+  append_to_statement_list_force (build1 (LABEL_EXPR, void_type_node,
+					  if_label), &loop);
+  cmp_expr = build2 (LT_EXPR, boolean_type_node, loop_var,
+		     build_int_cst (integer_type_node, vlength));
+  cond_expr = build3 (COND_EXPR, void_type_node, cmp_expr,
+		      build1 (GOTO_EXPR, void_type_node, body_label),
+		      build1 (GOTO_EXPR, void_type_node, exit_label));
+
+  append_to_statement_list_force (cond_expr, &loop);
+  append_to_statement_list_force (build1 (LABEL_EXPR, void_type_node,
+					  body_label), &loop);
+  append_to_statement_list_force (fn_body, &loop);
+
+  incr_expr = build2 (MODIFY_EXPR, void_type_node, loop_var,
+		      build2 (PLUS_EXPR, TREE_TYPE (loop_var), loop_var,
+			      build_int_cst (integer_type_node, 1)));
+
+  append_to_statement_list_force (incr_expr, &loop);
+  append_to_statement_list_force (build1 (GOTO_EXPR, void_type_node, if_label),
+				  &loop);
+  append_to_statement_list_force (build1 (LABEL_EXPR, void_type_node,
+					  exit_label), &loop);
+  
+  if (TREE_CODE (DECL_SAVED_TREE (fndecl)) == BIND_EXPR)
+    BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl)) = loop;
+  else
+    DECL_SAVED_TREE (fndecl) = loop;
+
+  pop_cfun ();
+  current_function_decl = old_fndecl;
+  
+  return loop_var;
+}
+
+/* This function will add the mask if statement for masked clone.  */
+
+static void
+add_elem_fn_mask (tree fndecl)
+{
+  tree ii_arg;
+  tree cond_expr, cmp_expr, old_fndecl;
+  tree fn_body = NULL_TREE;
+
+  old_fndecl = current_function_decl;
+  push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+  current_function_decl = fndecl;
+  
+  if (!DECL_SAVED_TREE (fndecl))
+    return;
+  
+  for (ii_arg = DECL_ARGUMENTS (fndecl); DECL_CHAIN (ii_arg);
+       ii_arg = DECL_CHAIN (ii_arg))
+    {
+      ;
+    }
+  if (TREE_CODE (DECL_SAVED_TREE (fndecl)) == BIND_EXPR)
+    fn_body = BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl));
+  else
+    fn_body = DECL_SAVED_TREE (fndecl); /* Not sure if we ever get here.  */
+
+  gcc_assert (DECL_NAME (ii_arg) == get_identifier ("__elem_fn_mask"));
+
+  cmp_expr = fold_build2 (NE_EXPR, TREE_TYPE (ii_arg), ii_arg,
+			  build_int_cst (TREE_TYPE (TREE_TYPE (ii_arg)), 0));
+  cond_expr = fold_build3 (COND_EXPR, void_type_node, cmp_expr, fn_body,
+			   build_empty_stmt (UNKNOWN_LOCATION));
+
+  if (TREE_CODE (DECL_SAVED_TREE (fndecl)) == BIND_EXPR)
+    BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl)) = cond_expr;
+  else
+    DECL_SAVED_TREE (fndecl) = cond_expr;
+
+  pop_cfun ();
+  current_function_decl = old_fndecl;
+  
+  return;
+ 
+}
+
+/* This function will do hacks necessary to recognize the cloned function.  */
+
+static void
+call_graph_add_fn (tree fndecl)
+{
+  const tree outer = current_function_decl;
+  struct function *f = DECL_STRUCT_FUNCTION (fndecl);
+
+  if (cfun)
+    f->curr_properties = cfun->curr_properties;
+  push_cfun (f);
+  current_function_decl = fndecl;
+  
+  cgraph_add_new_function (fndecl, false);
+  cgraph_finalize_function (fndecl, true);
+
+  pop_cfun ();
+  current_function_decl = outer;
+
+  return;
+}
+
+/* Function to create clones for function marked with vector attribute.  */
+
+void
+elem_fn_create_fn (tree fndecl)
+{
+  tree new_masked_fn = NULL_TREE, new_unmasked_fn = NULL_TREE;
+  tree induction_var = NULL_TREE;
+  elem_fn_info *elem_fn_values = NULL;
+  char *masked_suffix = NULL, *unmasked_suffix = NULL;
+  tree proc_attr = NULL_TREE, opp_proc_attr = NULL_TREE, opt_attr = NULL_TREE;
+
+  if (!fndecl)
+    return;
+
+  elem_fn_values = extract_elem_fn_values (fndecl);
+  if (!elem_fn_values)
+    return;
+
+  if (elem_fn_values->mask == USE_MASK)
+    masked_suffix = find_suffix (elem_fn_values, true);
+  else if (elem_fn_values->mask == USE_NOMASK)
+    unmasked_suffix = find_suffix (elem_fn_values, false);
+  else
+    {
+      masked_suffix   = find_suffix (elem_fn_values, true);
+      unmasked_suffix = find_suffix (elem_fn_values, false);
+    }
+  if (masked_suffix)
+    {
+      new_masked_fn = copy_node (fndecl);
+      new_masked_fn = rename_elem_fn (new_masked_fn, masked_suffix);
+      SET_DECL_RTL (new_masked_fn, NULL);
+      TREE_SYMBOL_REFERENCED (DECL_NAME (new_masked_fn)) = 1;
+      tree_elem_fn_versioning (fndecl, new_masked_fn, NULL, false, NULL, false,
+			       NULL, NULL, elem_fn_values->vectorlength[0],
+			       true);
+      proc_attr = create_processor_attribute (elem_fn_values, &opp_proc_attr);
+      if (proc_attr)
+	decl_attributes (&new_masked_fn, proc_attr, 0);
+      if (opp_proc_attr)
+	decl_attributes (&fndecl, opp_proc_attr, 0);
+      
+      opt_attr = create_optimize_attribute (3); /* Turn vectorizer on.  */
+      if (opt_attr)
+	decl_attributes (&new_masked_fn, opt_attr, 0);
+
+      DECL_ATTRIBUTES (new_masked_fn) =
+	remove_attribute ("vector", DECL_ATTRIBUTES (new_masked_fn));
+	
+      add_elem_fn_mask (new_masked_fn);
+      induction_var = add_elem_fn_loop (new_masked_fn,
+					elem_fn_values->vectorlength[0]);
+      fix_elem_fn_return_value (new_masked_fn, induction_var);
+      call_graph_add_fn (new_masked_fn);
+      SET_DECL_ASSEMBLER_NAME (new_masked_fn, DECL_NAME (new_masked_fn));
+      DECL_ELEM_FN_ALREADY_CLONED (new_masked_fn) = true;
+      if (DECL_STRUCT_FUNCTION (new_masked_fn))
+	DECL_STRUCT_FUNCTION (new_masked_fn)->elem_fn_already_cloned = true;
+    }
+  if (unmasked_suffix)
+    {
+      new_unmasked_fn = copy_node (fndecl);
+      new_unmasked_fn = rename_elem_fn (new_unmasked_fn, unmasked_suffix);
+      SET_DECL_RTL (new_unmasked_fn, NULL);
+      TREE_SYMBOL_REFERENCED (DECL_NAME (new_unmasked_fn)) = 1;
+      tree_elem_fn_versioning (fndecl, new_unmasked_fn, NULL, false, NULL,
+			       false, NULL, NULL,
+			       elem_fn_values->vectorlength[0], false);
+      proc_attr = create_processor_attribute (elem_fn_values, &opp_proc_attr);
+      if (proc_attr)
+	decl_attributes (&new_unmasked_fn, proc_attr, 0);
+      if (opp_proc_attr)
+	decl_attributes (&fndecl, opp_proc_attr, 0);
+      
+      opt_attr = create_optimize_attribute (3); /* Turn vectorizer on.  */
+      if (opt_attr)
+	decl_attributes (&new_unmasked_fn, opt_attr, 0);
+
+      DECL_ATTRIBUTES (new_unmasked_fn) =
+	remove_attribute ("vector", DECL_ATTRIBUTES (new_unmasked_fn));
+      induction_var = add_elem_fn_loop (new_unmasked_fn,
+					elem_fn_values->vectorlength[0]);
+      fix_elem_fn_return_value (new_unmasked_fn, induction_var);
+      call_graph_add_fn (new_unmasked_fn);
+      SET_DECL_ASSEMBLER_NAME (new_unmasked_fn, DECL_NAME (new_unmasked_fn));
+      DECL_ELEM_FN_ALREADY_CLONED (new_unmasked_fn) = true;
+      if (DECL_STRUCT_FUNCTION (new_unmasked_fn))
+	DECL_STRUCT_FUNCTION (new_unmasked_fn)->elem_fn_already_cloned = true;
+    }
+
+  free (elem_fn_values);
+  return;
+}
diff --git gcc/c-family/c.opt gcc/c-family/c.opt
index 914d110..0282e75 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -755,6 +755,10 @@  Recognize built-in functions
 fbuiltin-
 C ObjC C++ ObjC++ Joined
 
+fcilkplus
+C ObjC C++ ObjC++ LTO Report Var(flag_enable_cilkplus) Init(0)
+Enable Cilk Plus
+
 fcheck-new
 C++ ObjC++ Var(flag_check_new)
 Check the return value of new
diff --git gcc/c/c-decl.c gcc/c/c-decl.c
index e5d17b7..0b44f70 100644
--- gcc/c/c-decl.c
+++ gcc/c/c-decl.c
@@ -639,7 +639,8 @@  bind (tree name, tree decl, struct c_scope *scope, bool invisible,
   b->shadowed = 0;
   b->decl = decl;
   b->id = name;
-  b->depth = scope->depth;
+  if (scope) 
+    b->depth = scope->depth;
   b->invisible = invisible;
   b->nested = nested;
   b->inner_comp = 0;
@@ -648,10 +649,13 @@  bind (tree name, tree decl, struct c_scope *scope, bool invisible,
 
   b->u.type = NULL;
 
-  b->prev = scope->bindings;
-  scope->bindings = b;
+  if (scope) 
+    { 
+      b->prev = scope->bindings; 
+      scope->bindings = b;
+    }
 
-  if (decl_jump_unsafe (decl))
+  if (scope && decl_jump_unsafe (decl))
     scope->has_jump_unsafe_decl = 1;
 
   if (!name)
@@ -677,7 +681,7 @@  bind (tree name, tree decl, struct c_scope *scope, bool invisible,
   /* Locate the appropriate place in the chain of shadowed decls
      to insert this binding.  Normally, scope == current_scope and
      this does nothing.  */
-  while (*here && (*here)->depth > scope->depth)
+  while (scope && *here && (*here)->depth > scope->depth)
     here = &(*here)->shadowed;
 
   b->shadowed = *here;
diff --git gcc/c/c-lang.c gcc/c/c-lang.c
index ae1b081..c49e09d 100644
--- gcc/c/c-lang.c
+++ gcc/c/c-lang.c
@@ -33,7 +33,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #include "c-objc-common.h"
 #include "c-family/c-pragma.h"
-
+#include "cilkplus.h"
 enum c_language_kind c_language = clk_c;
 
 /* Lang hooks common to C and ObjC are declared in c-objc-common.h;
diff --git gcc/c/c-lang.h gcc/c/c-lang.h
index 33271dc..78d9e60 100644
--- gcc/c/c-lang.h
+++ gcc/c/c-lang.h
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  If not see
 
 #include "c-family/c-common.h"
 #include "ggc.h"
+#include "cilkplus.h"
 
 struct GTY((variable_size)) lang_type {
   /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
diff --git gcc/c/c-objc-common.c gcc/c/c-objc-common.c
index 9351cd5..4c284c1 100644
--- gcc/c/c-objc-common.c
+++ gcc/c/c-objc-common.c
@@ -30,6 +30,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "langhooks.h"
 #include "c-objc-common.h"
+#include "cilkplus.h"
 
 static bool c_tree_printer (pretty_printer *, text_info *, const char *,
 			    int, bool, bool, bool);
diff --git gcc/c/c-objc-common.h gcc/c/c-objc-common.h
index dbbd50a..786e922 100644
--- gcc/c/c-objc-common.h
+++ gcc/c/c-objc-common.h
@@ -106,4 +106,7 @@  along with GCC; see the file COPYING3.  If not see
 #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
 #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
 
+#undef LANG_HOOKS_ELEM_FN_CREATE_FN
+#define LANG_HOOKS_ELEM_FN_CREATE_FN elem_fn_create_fn
+
 #endif /* GCC_C_OBJC_COMMON */
diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index bea9791..d4a7553 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -208,6 +208,7 @@  typedef struct GTY(()) c_parser {
 
 static GTY (()) c_parser *the_parser;
 
+static VEC(tree,gc) *c_parser_elem_fn_expr_list (c_parser *parser);
 /* Read in and lex a single token, storing it in *TOKEN.  */
 
 static void
@@ -1668,6 +1669,14 @@  c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	      tree d = start_decl (declarator, specs, false,
 				   chainon (postfix_attrs,
 					    all_prefix_attrs));
+	      /* In Cilk Plus, when we have elemental function, we must know
+		 the name of the parameter variables to resolve
+		 dependency info. specified in the clause.  */
+	      if (flag_enable_cilkplus && d && TREE_CODE (d) == FUNCTION_DECL
+		  && declarator->kind == cdk_function
+		  && lookup_attribute ("vector", all_prefix_attrs)
+		  && declarator && declarator->u.arg_info)
+		DECL_ARGUMENTS (d) = declarator->u.arg_info->parms;
 	      if (d)
 		finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
 			     NULL_TREE, asm_name);
@@ -3585,8 +3594,17 @@  c_parser_attributes (c_parser *parser)
 		{
 		  tree tree_list;
 		  c_parser_consume_token (parser);
-		  expr_list = c_parser_expr_list (parser, false, true,
-						  NULL, NULL);
+
+		  /* For Cilk Plus, "vector" attribute indicates that we have
+		     an elemental function.  */
+		  if (flag_enable_cilkplus
+		      && TREE_CODE (attr_name) == IDENTIFIER_NODE
+		      && simple_cst_equal (attr_name,
+					   get_identifier ("vector")) == 1)
+		    expr_list = c_parser_elem_fn_expr_list (parser);
+		  else
+		    expr_list = c_parser_expr_list (parser, false, true,
+						    NULL, NULL);
 		  tree_list = build_tree_list_vec (expr_list);
 		  attr_args = tree_cons (NULL_TREE, arg1, tree_list);
 		  release_tree_vector (expr_list);
@@ -3598,8 +3616,16 @@  c_parser_attributes (c_parser *parser)
 		attr_args = NULL_TREE;
 	      else
 		{
-		  expr_list = c_parser_expr_list (parser, false, true,
-						  NULL, NULL);
+		  /* For Cilk Plus, vector attribute implies we have an
+		     elemental function.  */
+		  if (flag_enable_cilkplus
+		      && TREE_CODE (attr_name) == IDENTIFIER_NODE
+		      && simple_cst_equal (attr_name,
+					   get_identifier ("vector")) == 1)
+		    expr_list = c_parser_elem_fn_expr_list (parser);
+		  else
+		    expr_list = c_parser_expr_list (parser, false, true,
+						    NULL, NULL);
 		  attr_args = build_tree_list_vec (expr_list);
 		  release_tree_vector (expr_list);
 		}
@@ -10889,4 +10915,427 @@  c_parse_file (void)
   the_parser = NULL;
 }
 
+/* This function parses Cilk Plus elemental function processor clauses.  */
+
+static tree
+c_parser_elem_fn_processor_clause (c_parser *parser)
+{
+  c_token *token;
+  tree proc_tree_list = NULL_TREE;
+  VEC(tree,gc) *proc_vec_list = NULL;
+
+  token = c_parser_peek_token (parser);
+  if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_error (parser, "expected %<)%>");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return NULL_TREE;
+    }
+  else
+    c_parser_consume_token (parser);
+
+  proc_vec_list = make_tree_vector ();
+  
+  if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      token = c_parser_peek_token (parser);
+      if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	  && simple_cst_equal (token->value, get_identifier ("pentium_4")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  VEC_safe_push (tree, gc, proc_vec_list,
+			 build_string (strlen ("pentium_4"), "pentium_4"));
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("pentium_4_sse3")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  VEC_safe_push (tree, gc, proc_vec_list,
+			 build_string (strlen ("pentium_4_sse3"),
+				       "pentium_4_sse3"));
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("core2_duo_sse3")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  VEC_safe_push (tree, gc, proc_vec_list,
+			 build_string (strlen ("core2_duo_sse3"),
+				       "core2_duo_sse3"));
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("core_2_duo_sse_4_1")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  VEC_safe_push (tree, gc, proc_vec_list,
+			 build_string (strlen ("core_2_duo_sse_4_1"),
+				       "core_2_duo_sse_4_1"));
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("core_i7_sse4_2")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  VEC_safe_push (tree, gc, proc_vec_list,
+			 build_string (strlen ("core_i7_sse4_2"),
+				       "core_i7_sse4_2"));
+	}
+      else
+	sorry ("Processor type not supported");
+	
+      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+	c_parser_consume_token (parser);
+      else
+	c_parser_error (parser, "expected %>)%>");
+    }
+  else
+    c_parser_error (parser, "expected %>(%> and CPUID");
+
+  proc_tree_list = build_tree_list_vec (proc_vec_list);
+  release_tree_vector (proc_vec_list);
+  proc_tree_list = build_tree_list (get_identifier ("processor"),
+				    proc_tree_list);
+  return proc_tree_list;
+}
+
+/* This function parses the uniform clause of Cilk Plus elemental functions.  */
+
+static tree
+c_parser_elem_fn_uniform_clause (c_parser *parser)
+{
+  c_token *token;
+  tree uniform_tree;
+  tree str_token = NULL_TREE;
+  VEC(tree,gc) *uniform_vec = NULL;
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_error (parser, "expected %<)%>");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return NULL_TREE;
+    }
+  else
+    c_parser_consume_token (parser);
+  
+  uniform_vec =  make_tree_vector ();
+  while (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      token = c_parser_peek_token (parser);
+      if (token->value && token->type == CPP_NAME)
+	{
+	  /* Convert the variable to a string.  */
+	  str_token = build_string (strlen (IDENTIFIER_POINTER (token->value)),
+				    IDENTIFIER_POINTER (token->value));
+	  VEC_safe_push (tree, gc, uniform_vec, str_token);
+	  c_parser_consume_token (parser);
+	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is_not (parser, CPP_NAME))
+		{
+		  c_parser_error (parser, "expected identifier after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return NULL_TREE;
+		}
+	    }
+	  else if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	    {
+	      c_parser_error (parser,
+			      "expected %<,%> or %<)%> after identifier");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+	      return NULL_TREE;
+	    }
+	}
+      else
+	{
+	  c_parser_error (parser, "expected number or comma");
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+	  return NULL_TREE;
+	}
+    }
+  c_parser_consume_token (parser);     
+  uniform_tree = build_tree_list_vec (uniform_vec);
+  release_tree_vector (uniform_vec);
+  uniform_tree = build_tree_list (get_identifier ("uniform"), uniform_tree);
+  return uniform_tree;
+}
+
+/* This function parses the linear clause of Cilk Plus Elemental functions.  */
+
+static tree
+c_parser_elem_fn_linear_clause (c_parser *parser)
+{
+  c_token *token;
+  VEC(tree,gc) *linear_vec = NULL;
+  tree linear_tree = NULL_TREE;
+  tree var_str, step_size;
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_error (parser, "expected %<)%>");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return NULL_TREE;
+    }
+  else
+    c_parser_consume_token (parser);
+  linear_vec = make_tree_vector ();
+
+  while (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      token = c_parser_peek_token (parser);
+      if (token->value && token->type == CPP_NAME)
+	{
+	  var_str = build_string (strlen (IDENTIFIER_POINTER (token->value)),
+				  IDENTIFIER_POINTER (token->value));
+	  c_parser_consume_token (parser);
+	  if (c_parser_next_token_is (parser, CPP_COLON))
+	    {
+	      c_parser_consume_token (parser);
+	      token = c_parser_peek_token (parser);
+	      if (token->value && token->type == CPP_NUMBER)
+		step_size = token->value;
+	      else
+		{
+		  c_parser_error (parser, "expected step-size");
+		  return NULL_TREE;
+		}
+	      c_parser_consume_token (parser);
+	    }
+	  else
+	    step_size = integer_one_node;
+	  VEC_safe_push (tree, gc, linear_vec, var_str);
+	  VEC_safe_push (tree, gc, linear_vec, step_size);
+	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is_not (parser, CPP_NAME))
+		{
+		  c_parser_error (parser,
+				  "expected variable after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return NULL_TREE;
+		}
+	    }
+	  else if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	    {
+	      c_parser_error (parser,
+			      "expected %<,%> or %<)%> after variable/step");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+	      return NULL_TREE;
+	    }
+	}
+      else
+	{
+	  c_parser_error (parser, "expected variable name or comma");
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+	  return NULL_TREE;
+	}
+    }
+  c_parser_consume_token (parser); /* Consume the ')'.  */
+  linear_tree = build_tree_list_vec (linear_vec);
+  release_tree_vector (linear_vec);
+  linear_tree = build_tree_list (get_identifier ("linear"), linear_tree);
+  return linear_tree;
+}
+
+/* This function parses the vectorlength clause of Elemental function.  */
+
+static tree
+c_parser_elem_fn_vlength_clause (c_parser *parser)
+{
+  c_token *token;
+  VEC(tree,gc) *vlength_vec = NULL;
+  tree vlength_tree = NULL_TREE;
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      c_parser_error (parser, "expected %<)%>");
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+      return NULL_TREE;
+    }
+  else
+    c_parser_consume_token (parser);
+
+  vlength_vec = make_tree_vector ();
+  while (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      token = c_parser_peek_token (parser);
+      if (token->value && token->type == CPP_NUMBER)
+	{
+	  VEC_safe_push (tree, gc, vlength_vec, token->value);
+	  c_parser_consume_token (parser);
+	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is_not (parser, CPP_NUMBER))
+		{
+		  c_parser_error (parser, "expected vectorlength after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return NULL_TREE;
+		}
+	    }
+	  else if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+	    {
+	      c_parser_error (parser,
+			      "expected %<,%> or %<)%> after vectorlength");
+	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+	      return NULL_TREE;
+	    }
+	}
+      else
+	{
+	  c_parser_error (parser, "expected number or comma");
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+	  return NULL_TREE;
+	}
+    }
+  c_parser_consume_token (parser);
+  vlength_tree = build_tree_list_vec (vlength_vec);
+  release_tree_vector (vlength_vec);
+  vlength_tree = build_tree_list (get_identifier ("vectorlength"),
+				  vlength_tree);
+  return vlength_tree;
+}
+
+/* This function parses the Elemental function attribute list.  */
+
+static VEC(tree,gc) *
+c_parser_elem_fn_expr_list (c_parser *parser)
+{
+  c_token *token;
+  VEC(tree,gc) *expr_list = NULL;
+  tree proc_list = NULL_TREE, mask_list = NULL_TREE, uniform_list = NULL_TREE;
+  tree vlength_list = NULL_TREE, linear_list = NULL_TREE;
+
+  expr_list = make_tree_vector ();
+
+  while (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+    {
+      token = c_parser_peek_token (parser);
+      if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	  && simple_cst_equal (token->value,
+			       get_identifier ("processor")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  gcc_assert (proc_list == NULL_TREE);
+	  proc_list = c_parser_elem_fn_processor_clause (parser);
+	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+		{
+		  c_parser_error (parser, "expected identifier after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return expr_list;
+		}
+	    }
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("mask")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  gcc_assert (mask_list == NULL_TREE);
+	  mask_list = get_identifier ("mask");
+	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+		{
+		  c_parser_error (parser, "expected identifier after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return expr_list;
+		}
+	    }	 
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("nomask")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  gcc_assert (mask_list == NULL_TREE);
+	  mask_list = get_identifier ("nomask");
+	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+		{
+		  c_parser_error (parser, "expected identifier after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return expr_list;
+		}
+	    }	  
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("vectorlength")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  gcc_assert (vlength_list == NULL_TREE);
+	  vlength_list = c_parser_elem_fn_vlength_clause (parser);
+	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+		{
+		  c_parser_error (parser, "expected identifier after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return expr_list;
+		}
+	    }	  
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("uniform")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  gcc_assert (uniform_list == NULL_TREE);
+	  uniform_list = c_parser_elem_fn_uniform_clause (parser);
+	  	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+		{
+		  c_parser_error (parser, "expected identifier after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return expr_list;
+		}
+	    }
+	}
+      else if (token->value && TREE_CODE (token->value) == IDENTIFIER_NODE
+	       && simple_cst_equal (token->value,
+				    get_identifier ("linear")) == 1)
+	{
+	  c_parser_consume_token (parser);
+	  gcc_assert (linear_list == NULL_TREE);
+	  linear_list = c_parser_elem_fn_linear_clause (parser);
+	  	  if (c_parser_next_token_is (parser, CPP_COMMA))
+	    {
+	      c_parser_consume_token (parser);
+	      if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+		{
+		  c_parser_error (parser, "expected identifier after %<,%>");
+		  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+		  return expr_list;
+		}
+	    }
+	}
+    }
+
+  if (proc_list)
+    VEC_safe_push (tree, gc, expr_list, proc_list);
+  if (vlength_list)
+    VEC_safe_push (tree, gc, expr_list, vlength_list);
+  if (uniform_list)
+    VEC_safe_push (tree, gc, expr_list, uniform_list);
+  if (mask_list)
+    VEC_safe_push (tree, gc, expr_list, mask_list);
+  if (linear_list)
+    VEC_safe_push (tree, gc, expr_list, linear_list);
+  
+  return expr_list;
+}
+
 #include "gt-c-c-parser.h"
diff --git gcc/cgraph.h gcc/cgraph.h
index 0d2ad41..d6efc5c 100644
--- gcc/cgraph.h
+++ gcc/cgraph.h
@@ -641,6 +641,8 @@  struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
 						basic_block, const char *);
 void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*,
 			       bool, bitmap, bool, bitmap, basic_block);
+void tree_elem_fn_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, 
+			      bitmap, bool, bitmap, basic_block, int, bool);
 
 /* In cgraphbuild.c  */
 unsigned int rebuild_cgraph_edges (void);
diff --git gcc/cgraphunit.c gcc/cgraphunit.c
index 2dd0871..015c285 100644
--- gcc/cgraphunit.c
+++ gcc/cgraphunit.c
@@ -225,15 +225,24 @@  static GTY (()) tree vtable_entry_type;
 static bool
 cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
 {
+  bool is_cloned_elem_func = false;
+  
   /* If the user told us it is used, then it must be so.  */
   if (node->symbol.force_output)
     return true;
 
+  /* When an elemental function is cloned, variable elem_fn_already_cloned
+     will be set to true, for all other functions, it is initalized to zero.
+     So, if it is an elemental function, we output it without questioning.  */
+  if (flag_enable_cilkplus && DECL_STRUCT_FUNCTION (decl))
+    is_cloned_elem_func = DECL_STRUCT_FUNCTION (decl)->elem_fn_already_cloned;
+  
   /* Double check that no one output the function into assembly file
      early.  */
   gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
 	               || (node->thunk.thunk_p || node->same_body_alias)
-	               ||  !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
+	               ||  !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
+		       || is_cloned_elem_func);
 
 
   /* Keep constructors, destructors and virtual functions.  */
@@ -475,7 +484,12 @@  cgraph_add_new_function (tree fndecl, bool lowered)
 	break;
       case CGRAPH_STATE_CONSTRUCTION:
 	/* Just enqueue function to be processed at nearest occurrence.  */
-	node = cgraph_create_node (fndecl);
+	/* For Cilk Plus we need to use cgraph_get_create_node instead of
+	   cgraph_create_node.  */
+	if (flag_enable_cilkplus)
+	  node = cgraph_get_create_node (fndecl);
+	else
+	  node = cgraph_create_node (fndecl);
 	if (lowered)
 	  node->lowered = true;
 	if (!cgraph_new_nodes)
@@ -879,13 +893,18 @@  cgraph_analyze_functions (void)
 	   node != (symtab_node)first_analyzed
 	   && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
 	{
-	  if ((symtab_function_p (node)
-	       && cgraph (node)->local.finalized
-	       && cgraph_decide_is_function_needed (cgraph (node), node->symbol.decl))
-	      || (symtab_variable_p (node)
-		  && varpool (node)->finalized
-		  && !DECL_EXTERNAL (node->symbol.decl)
-		  && decide_is_variable_needed (varpool (node), node->symbol.decl)))
+	  if ((flag_enable_cilkplus
+	       && TREE_CODE (node->symbol.decl) == FUNCTION_DECL
+	       && DECL_ELEM_FN_ALREADY_CLONED (node->symbol.decl))
+	      || ((symtab_function_p (node)
+		   && cgraph (node)->local.finalized
+		   && cgraph_decide_is_function_needed (cgraph (node),
+							node->symbol.decl))
+		  || (symtab_variable_p (node)
+		      && varpool (node)->finalized
+		      && !DECL_EXTERNAL (node->symbol.decl)
+		      && decide_is_variable_needed (varpool (node),
+						    node->symbol.decl))))
 	    {
 	      enqueue_node (node);
 	      if (!changed && cgraph_dump_file)
@@ -989,10 +1008,18 @@  cgraph_analyze_functions (void)
       next = node->symbol.next;
       if (!node->symbol.aux && !referred_to_p (node))
 	{
-	  if (cgraph_dump_file)
-	    fprintf (cgraph_dump_file, " %s", symtab_node_name (node));
-	  symtab_remove_node (node);
-	  continue;
+	  if (flag_enable_cilkplus
+	      && TREE_CODE (node->symbol.decl) == FUNCTION_DECL
+	      && DECL_ELEM_FN_ALREADY_CLONED (node->symbol.decl))
+	    /* We do not remove a cloned elemental function.  */
+	    ;
+	  else
+	    {
+	      if (cgraph_dump_file)
+		fprintf (cgraph_dump_file, " %s", symtab_node_name (node));
+	      symtab_remove_node (node);
+	      continue;
+	    }
 	}
       if (symtab_function_p (node))
 	{
diff --git gcc/cilkplus.h gcc/cilkplus.h
new file mode 100644
index 0000000..7a20efc
--- /dev/null
+++ gcc/cilkplus.h
@@ -0,0 +1,87 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains Cilk Plus Support files.
+   Copyright (C) 2011, 2012  Free Software Foundation, Inc.
+   Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+   Intel Corporation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CILKPLUS_H
+#define GCC_CILKPLUS_H
+
+#include "tree.h"
+
+/* This is the max number of data we have have in elem-function arrays.  */
+#define MAX_VARS 50
+
+/* These are different mask options.  I put 12345 so that we can defferenciate
+   the value during debugging.  */
+enum mask_options {
+  USE_MASK = 12345,
+  USE_NOMASK,
+  USE_BOTH
+};
+
+/* This data structure will hold all the data from the vector attribute.  */
+typedef struct
+{
+  char *proc_type;
+  enum mask_options mask;
+  int vectorlength[MAX_VARS];
+  int no_vlengths;
+  char *uniform_vars[MAX_VARS];
+  int no_uvars;
+  int uniform_location[MAX_VARS]; /* Their location in parm list.  */
+  char *linear_vars[MAX_VARS];
+  int linear_steps[MAX_VARS];
+  int linear_location[MAX_VARS]; /* Their location in parm list.  */
+  int no_lvars;
+  int private_location[MAX_VARS]; /* Parm not in uniform or linear list. */
+  int no_pvars;
+  char *func_prefix;
+  int total_no_args;
+} elem_fn_info;
+
+/* This data structure will hold all the arguments in the function.  */
+typedef struct
+{
+  tree induction_var;
+  tree arguments;
+  tree return_var;
+} fn_vect_elements;
+
+enum elem_fn_parm_type
+{ 
+  TYPE_NONE = 0, 
+  TYPE_UNIFORM = 1, 
+  TYPE_LINEAR = 2
+};
+
+
+bool is_elem_fn (tree);
+tree find_elem_fn_name (tree, tree, tree);
+void elem_fn_create_fn (tree);
+char *find_processor_code (elem_fn_info *);
+char *find_vlength_code (elem_fn_info *);
+tree rename_elem_fn (tree, const char *);
+char *find_suffix (elem_fn_info *, bool);
+enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree, tree *);
+tree find_elem_fn_name (tree, tree, tree);
+elem_fn_info *extract_elem_fn_values (tree);
+void elem_fn_create_fn (tree);
+
+#endif
diff --git gcc/config/i386/i386.c gcc/config/i386/i386.c
index 62d3a8c..eca39d9 100644
--- gcc/config/i386/i386.c
+++ gcc/config/i386/i386.c
@@ -40572,6 +40572,113 @@  ix86_memmodel_check (unsigned HOST_WIDE_INT val)
   return val;
 }
 
+/* Return the specific arch attribute for the processor clause of Elemental
+   function in Cilk Plus. */
+
+static tree
+ix86_cilkplus_map_proc_to_attr (char *proc_name, tree *opposite_attr)
+{
+  /* You will need the opposite attribute for the scalar code part.  */
+  tree proc_attr, opp_proc_attr;
+  VEC(tree,gc) *proc_vec_list = VEC_alloc (tree, gc, 4);
+  VEC(tree,gc) *opp_proc_vec_list = VEC_alloc (tree, gc, 4);
+  
+  if (!proc_name)
+    return NULL_TREE;
+
+  if (!strcmp (proc_name, "pentium_4"))
+    {
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("arch=pentium4"), "arch=pentium4"));
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("mmx"), "mmx"));
+      if (opposite_attr)
+	{
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("no-mmx"), "no-mmx"));
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("arch=pentium4"),
+				       "arch=pentium4"));
+	}
+    }
+  else if (!strcmp (proc_name, "pentium_4_sse3"))
+    {
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("arch=pentium4"), "arch=pentium4"));
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("sse3"), "sse3"));
+      if (opposite_attr)
+	{
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("arch=pentium4"),
+				       "arch=pentium4"));
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("no-sse3"), "no-sse3"));
+	}
+    }
+  else if (!strcmp (proc_name, "core2_duo_sse3"))
+    {
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("arch=core2"), "arch=core2"));
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("sse3"), "sse3"));
+      if (opposite_attr)
+	{
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("arch=core2"), "arch=core2"));
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("no-sse3"), "no-sse3"));
+	}
+    }
+  else if (!strcmp (proc_name, "core_2_duo_sse_4_1"))
+    {
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("arch=core2"), "arch=core2"));
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("sse4.1"), "sse4.1"));
+      if (opposite_attr)
+	{
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("arch=core2"), "arch=core2"));
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("no-sse4.1"), "no-sse4.1"));
+	}
+    }
+  else if (!strcmp (proc_name, "core_i7_sse4_2"))
+    {
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("arch=corei7"), "arch=corei7"));
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("sse4.2"), "sse4.2"));
+      VEC_safe_push (tree, gc, proc_vec_list,
+		     build_string (strlen ("avx"), "avx"));
+      if (opposite_attr)
+	{
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("arch=corei7"), "arch=corei7"));
+	  VEC_safe_push (tree, gc, opp_proc_vec_list,
+			 build_string (strlen ("no-sse4.2"), "no-sse4.2"));
+	}
+    }
+  else
+    sorry ("Processor type not supported.");
+
+  proc_attr = build_tree_list_vec (proc_vec_list);
+  VEC_truncate (tree, proc_vec_list, 0);
+  proc_attr = build_tree_list (get_identifier ("__target__"), proc_attr);
+
+  if (opposite_attr)
+    {
+      opp_proc_attr = build_tree_list_vec (opp_proc_vec_list);
+      VEC_truncate (tree, opp_proc_vec_list, 0);
+      opp_proc_attr = build_tree_list (get_identifier ("__target__"),
+				       opp_proc_attr);
+      *opposite_attr = opp_proc_attr;
+    }
+  return proc_attr;
+}
+
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
@@ -40907,6 +41014,11 @@  ix86_memmodel_check (unsigned HOST_WIDE_INT val)
 #define TARGET_INIT_LIBFUNCS darwin_rename_builtins
 #endif
 
+#undef TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR
+#define TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR \
+  ix86_cilkplus_map_proc_to_attr
+
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-i386.h"
diff --git gcc/doc/tm.texi gcc/doc/tm.texi
index 11b2f9a..2108133 100644
--- gcc/doc/tm.texi
+++ gcc/doc/tm.texi
@@ -5713,6 +5713,11 @@  For vector memory operations the cost may depend on type (@var{vectype}) and
 misalignment value (@var{misalign}).
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR (char *@var{}, tree *@var{})
+This hook is called by a Cilk Plus routine that will be used to map the
+processor clause to the appropriate arch and tune attributes.
+@end deftypefn
+
 @deftypefn {Target Hook} bool TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE (const_tree @var{type}, bool @var{is_packed})
 Return true if vector alignment is reachable (by peeling N iterations) for the given type.
 @end deftypefn
diff --git gcc/doc/tm.texi.in gcc/doc/tm.texi.in
index 54414f1..cd94017 100644
--- gcc/doc/tm.texi.in
+++ gcc/doc/tm.texi.in
@@ -5637,6 +5637,8 @@  For vector memory operations the cost may depend on type (@var{vectype}) and
 misalignment value (@var{misalign}).
 @end deftypefn
 
+@hook TARGET_CILKPLUS_BUILTIN_MAP_PROCESSOR_TO_ATTR
+
 @hook TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE
 Return true if vector alignment is reachable (by peeling N iterations) for the given type.
 @end deftypefn
diff --git gcc/elem-function-common.c gcc/elem-function-common.c
new file mode 100644
index 0000000..22edb6d
--- /dev/null
+++ gcc/elem-function-common.c
@@ -0,0 +1,482 @@ 
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+   This file contains the language independent functions for
+   Elemental functions.
+   
+   Copyright (C) 2012  Free Software Foundation, Inc.
+   Written by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+              Intel Corporation
+
+   Many Thanks to Karthik Kumar for advice on the basic technique
+   about cloning functions.
+   
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "basic-block.h"
+#include "output.h"
+#include "diagnostic.h"
+#include "tree-flow.h"
+#include "tree-dump.h"
+#include "tree-pass.h"
+#include "timevar.h"
+#include "tree-inline.h"
+#include "cgraph.h"
+#include "ipa-prop.h"
+#include "opts.h"
+#include "tree-iterator.h"
+#include "vec.h"
+#include "cilkplus.h"
+
+#define MAX_VARS 50
+
+enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree, tree *);
+bool is_elem_fn (tree);
+tree find_elem_fn_name (tree old_fndecl, tree vectype_out, tree vectype_in);
+elem_fn_info *extract_elem_fn_values (tree decl);
+
+/* This function will find the appropriate processor code in the function
+   mangling vector function.  */
+
+char *
+find_processor_code (elem_fn_info *elem_fn_values)
+{
+  if (!elem_fn_values || !elem_fn_values->proc_type)
+    return xstrdup ("B");
+
+  if (!strcmp (elem_fn_values->proc_type, "pentium_4"))
+    return xstrdup ("B");
+  else if (!strcmp (elem_fn_values->proc_type, "pentium_4_sse3"))
+    return xstrdup ("D");
+  else if (!strcmp (elem_fn_values->proc_type, "core2_duo_sse3"))
+    return xstrdup ("E");
+  else if (!strcmp (elem_fn_values->proc_type, "core_2_duo_sse_4_1"))
+    return xstrdup ("F");
+  else if (!strcmp (elem_fn_values->proc_type, "core_i7_sse4_2"))
+    return xstrdup ("H");
+  else
+    gcc_unreachable ();
+
+  return NULL; /* should never get here */
+}
+
+/* This function will return vectorlength, if specified, in string format -OR-
+   it will give the default vector length for the specified architecture.  */
+
+char *
+find_vlength_code (elem_fn_info *elem_fn_values)
+{
+  char *vlength_code = (char *) xmalloc (sizeof (char) * 10);
+  if (!elem_fn_values)
+    { 
+      sprintf (vlength_code, "4");
+      return vlength_code;
+    }
+
+  memset (vlength_code, 10, 0);
+  
+  if (elem_fn_values->no_vlengths != 0)
+    sprintf (vlength_code,"%d", elem_fn_values->vectorlength[0]);
+  else
+    {
+      if (!elem_fn_values->proc_type)
+	sprintf (vlength_code, "4");
+      else if (!strcmp (elem_fn_values->proc_type, "pentium_4"))
+	sprintf (vlength_code, "4");
+      else if (!strcmp (elem_fn_values->proc_type, "pentium_4_sse3"))
+	sprintf (vlength_code, "4");
+      else if (!strcmp (elem_fn_values->proc_type, "core2_duo_sse3"))
+	sprintf (vlength_code, "4");
+      else if (!strcmp (elem_fn_values->proc_type, "core_2_duo_sse_4_1"))
+	sprintf (vlength_code, "4");
+      else if (!strcmp (elem_fn_values->proc_type, "core_i7_sse4_2"))
+	sprintf (vlength_code, "4");
+      else
+	gcc_unreachable ();
+    }
+  return vlength_code;
+}
+
+
+/* This function will concatinate the suffix to the existing function decl.  */
+
+tree
+rename_elem_fn (tree decl, const char *suffix)
+{
+  int length = 0;
+  const char *fn_name = IDENTIFIER_POINTER (DECL_NAME (decl));
+  char *new_fn_name;
+  tree new_decl = NULL_TREE;
+  
+  if (!suffix || !fn_name)
+    return decl;
+  else
+    new_decl = decl;
+
+  length = strlen (fn_name) + strlen (suffix) + 1;
+  new_fn_name = (char *)xmalloc (length);
+  strcpy (new_fn_name, fn_name);
+  strcat (new_fn_name, suffix);
+
+  DECL_NAME (new_decl) = get_identifier (new_fn_name);
+  return new_decl;
+}
+
+
+/* This function will find the appropriate mangling suffix for the vector
+   function.  */
+
+char *
+find_suffix (elem_fn_info *elem_fn_values, bool masked)
+{
+  char *suffix = (char*)xmalloc (100);
+  char tmp_str[10];
+  int arg_number, ii_pvar, ii_uvar, ii_lvar;
+  strcpy (suffix, "._simdsimd_");
+  strcat (suffix, find_processor_code (elem_fn_values));
+  strcat (suffix, find_vlength_code (elem_fn_values));
+
+  if (masked)
+    strcat (suffix, "m");
+  else
+    strcat (suffix, "n");
+
+  for (arg_number = 0; arg_number <= elem_fn_values->total_no_args;
+       arg_number++)
+    {
+      for (ii_lvar = 0; ii_lvar < elem_fn_values->no_lvars; ii_lvar++)
+	{
+	  if (elem_fn_values->linear_location[ii_lvar] == arg_number)
+	    {
+	      strcat (suffix, "_l");
+	      sprintf (tmp_str, "%d", elem_fn_values->linear_steps[ii_lvar]);
+	      strcat (suffix, tmp_str);
+	    }
+	}
+      for (ii_uvar = 0; ii_uvar < elem_fn_values->no_uvars; ii_uvar++) 
+	if (elem_fn_values->uniform_location[ii_uvar] == arg_number) 
+	  strcat (suffix, "_s1");
+      for (ii_pvar = 0; ii_pvar < elem_fn_values->no_pvars; ii_pvar++) 
+	if (elem_fn_values->private_location[ii_pvar] == arg_number) 
+	  strcat (suffix, "_v1");
+    } 
+  return suffix;
+}
+
+
+/* This is an helper function for find_elem_fn_param_type.  */
+
+static enum elem_fn_parm_type
+find_elem_fn_parm_type_1 (tree fndecl, int parm_no, tree *step_size)
+{
+  int ii = 0;
+  elem_fn_info *elem_fn_values;
+
+  elem_fn_values = extract_elem_fn_values (fndecl);
+  if (!elem_fn_values)
+    return TYPE_NONE;
+
+  for (ii = 0; ii < elem_fn_values->no_lvars; ii++)
+    if (elem_fn_values->linear_location[ii] == parm_no)
+      {
+	if (step_size != NULL)
+	  *step_size = build_int_cst (integer_type_node,
+				      elem_fn_values->linear_steps[ii]);
+	return TYPE_LINEAR;
+      }
+    
+  for (ii = 0; ii < elem_fn_values->no_uvars; ii++)
+    if (elem_fn_values->uniform_location[ii] == parm_no)
+      return TYPE_UNIFORM;
+    
+  return TYPE_NONE;
+}
+  
+  
+/* This function will return the type of a parameter in elemental function.
+   The choices are UNIFORM or LINEAR.  */
+
+enum elem_fn_parm_type
+find_elem_fn_parm_type (gimple stmt, tree op, tree *step_size)
+{
+  tree fndecl, parm = NULL_TREE;
+  int ii, nargs;
+  enum elem_fn_parm_type return_type = TYPE_NONE;
+  
+  if (gimple_code (stmt) != GIMPLE_CALL)
+    return TYPE_NONE;
+
+  fndecl = gimple_call_fndecl (stmt);
+  gcc_assert (fndecl);
+
+  nargs = gimple_call_num_args (stmt);
+
+  for (ii = 0; ii < nargs; ii++)
+    {
+      parm = gimple_call_arg (stmt, ii);
+      if (op == parm)
+	{
+	  return_type = find_elem_fn_parm_type_1 (fndecl, ii, step_size);
+	  return return_type;
+	}
+    }
+  return return_type;
+}
+
+/* This function will return the appropriate cloned named for the function.  */
+
+tree
+find_elem_fn_name (tree old_fndecl, tree vectype_out, 
+		   tree vectype_in ATTRIBUTE_UNUSED)
+{
+  elem_fn_info *elem_fn_values = NULL;
+  tree new_fndecl = NULL_TREE, arg_type = NULL_TREE;
+  char *suffix = NULL;
+  
+  elem_fn_values = extract_elem_fn_values (old_fndecl);
+ 
+  if (elem_fn_values)
+    {
+      if (elem_fn_values->no_vlengths > 0)
+	{
+	  if (elem_fn_values->vectorlength[0] ==
+	      (int)TYPE_VECTOR_SUBPARTS (vectype_out))
+	    suffix = find_suffix (elem_fn_values, false);
+	  else
+	    return NULL_TREE;
+	}
+      else
+	return NULL_TREE;
+    }
+  else
+    return NULL_TREE;
+
+  new_fndecl = copy_node (rename_elem_fn (old_fndecl, suffix));
+  TREE_TYPE (new_fndecl) = copy_node (TREE_TYPE (old_fndecl));
+
+  TYPE_ARG_TYPES (TREE_TYPE (new_fndecl)) =
+    copy_list (TYPE_ARG_TYPES (TREE_TYPE (new_fndecl)));
+  
+  for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (new_fndecl));
+       arg_type && arg_type != void_type_node;
+       arg_type = TREE_CHAIN (arg_type))
+    TREE_VALUE (arg_type) = vectype_out;
+  
+  if (TREE_TYPE (TREE_TYPE (new_fndecl)) != void_type_node)
+    {
+      TREE_TYPE (TREE_TYPE (new_fndecl)) =
+	copy_node (TREE_TYPE (TREE_TYPE (new_fndecl)));
+      TREE_TYPE (TREE_TYPE (new_fndecl)) = vectype_out;
+      DECL_MODE (new_fndecl) = TYPE_MODE (vectype_out);
+    }
+  
+  return new_fndecl;
+}
+
+/* This function will extract the elem. function values from a vector and store
+   it in a data structure and return that.  */
+
+elem_fn_info *
+extract_elem_fn_values (tree decl)
+{
+  elem_fn_info *elem_fn_values = NULL;
+  int x = 0; /* this is a dummy variable */
+  int arg_number = 0, ii = 0;
+  tree ii_tree, jj_tree, kk_tree;
+  tree decl_attr = DECL_ATTRIBUTES (decl);
+  tree decl_ret_type;
+  if (!decl_attr)
+    return NULL;
+
+  elem_fn_values = (elem_fn_info *)xmalloc (sizeof (elem_fn_info));
+  gcc_assert (elem_fn_values);
+
+  decl_ret_type = TREE_TYPE (decl);
+  if (decl_ret_type)
+    decl_ret_type = TREE_TYPE (decl_ret_type);
+  
+  elem_fn_values->proc_type = NULL;
+  elem_fn_values->mask = USE_BOTH;
+  elem_fn_values->no_vlengths = 0;
+  elem_fn_values->no_uvars = 0;
+  elem_fn_values->no_lvars = 0;
+  elem_fn_values->no_pvars = 0;
+  if (decl_ret_type && COMPLETE_TYPE_P (decl_ret_type)
+      && !VOID_TYPE_P (decl_ret_type))
+    switch (compare_tree_int (TYPE_SIZE (decl_ret_type), 64))
+      {
+      case 0: /* This means they are equal.  */
+	elem_fn_values->vectorlength[0] = 2;
+	break;
+      case -1: /* This means it is less than 64.  */
+	elem_fn_values->vectorlength[0] = 4;
+	break;
+      default:
+	elem_fn_values->vectorlength[0] = 1;
+      }
+  
+
+  for (ii_tree = decl_attr; ii_tree; ii_tree = TREE_CHAIN (ii_tree))
+    {
+      tree ii_purpose = TREE_PURPOSE (ii_tree);
+      tree ii_value = TREE_VALUE (ii_tree);
+      if (TREE_CODE (ii_purpose) == IDENTIFIER_NODE
+	  && !strcmp (IDENTIFIER_POINTER (ii_purpose), "vector"))
+	{
+	  for (jj_tree = ii_value; jj_tree;
+	       jj_tree = TREE_CHAIN (jj_tree))
+	    {
+	      tree jj_purpose = NULL_TREE, jj_value = TREE_VALUE (jj_tree);
+
+	      /* This means we have a mask/nomask.  */
+	      if (TREE_CODE (jj_value) == IDENTIFIER_NODE)
+		{ 
+		  if (!strcmp (IDENTIFIER_POINTER (jj_value), "mask"))
+		    elem_fn_values->mask = USE_MASK;		    
+		  else if (!strcmp (IDENTIFIER_POINTER (jj_value), "nomask"))
+		    elem_fn_values->mask = USE_NOMASK;
+		  continue;
+		}
+	      else
+		jj_purpose = TREE_PURPOSE (jj_value);
+	      
+	      if (TREE_CODE (jj_purpose) == IDENTIFIER_NODE
+		  && !strcmp (IDENTIFIER_POINTER (jj_purpose), "processor"))
+		{
+		  for (kk_tree = TREE_VALUE (jj_value); kk_tree;
+		       kk_tree = TREE_CHAIN (kk_tree))
+		    {
+		      tree kk_value = TREE_VALUE (kk_tree);
+		      if (TREE_CODE (kk_value) == STRING_CST)
+			elem_fn_values->proc_type =
+			  xstrdup (TREE_STRING_POINTER (kk_value));
+		    }
+		}
+	      else if (TREE_CODE (jj_purpose) == IDENTIFIER_NODE
+		       && !strcmp (IDENTIFIER_POINTER (jj_purpose),
+				  "vectorlength"))
+		{
+		  for (kk_tree = TREE_VALUE (jj_value); kk_tree;
+		       kk_tree = TREE_CHAIN (kk_tree))
+		    {
+		      tree kk_value = TREE_VALUE (kk_tree);
+		      if (TREE_CODE (kk_value) == INTEGER_CST)
+			{
+			  x = elem_fn_values->no_vlengths;
+			  elem_fn_values->vectorlength[x] =
+			    (int) TREE_INT_CST_LOW (kk_value);
+			  elem_fn_values->no_vlengths++;
+			}
+		    }
+		}
+	      else if (TREE_CODE (jj_purpose) == IDENTIFIER_NODE
+		       && !strcmp (IDENTIFIER_POINTER (jj_purpose), "uniform"))
+		{
+		  for (kk_tree = TREE_VALUE (jj_value); kk_tree;
+		       kk_tree = TREE_CHAIN (kk_tree))
+		    {
+		      tree kk_value = TREE_VALUE (kk_tree);
+		      elem_fn_values->uniform_vars[elem_fn_values->no_uvars] =
+			xstrdup (TREE_STRING_POINTER (kk_value));
+		      elem_fn_values->no_uvars++;
+		    }
+		}
+	      else if (TREE_CODE (jj_purpose) == IDENTIFIER_NODE
+		       && !strcmp (IDENTIFIER_POINTER (jj_purpose), "linear"))
+		{
+		  for (kk_tree = TREE_VALUE (jj_value); kk_tree;
+		       kk_tree = TREE_CHAIN (kk_tree))
+		    {
+		      tree kk_value = TREE_VALUE (kk_tree);
+		      elem_fn_values->linear_vars[elem_fn_values->no_lvars] =
+			xstrdup (TREE_STRING_POINTER (kk_value));
+		      kk_tree = TREE_CHAIN (kk_tree);
+		      kk_value = TREE_VALUE (kk_tree);
+		      elem_fn_values->linear_steps[elem_fn_values->no_lvars] =
+			TREE_INT_CST_LOW (kk_value);
+		      elem_fn_values->no_lvars++;
+		    }
+		}
+	    }
+	}
+    }
+
+  for (ii_tree = DECL_ARGUMENTS (decl); ii_tree; ii_tree = DECL_CHAIN (ii_tree))
+    {
+      bool already_found = false;
+      for (ii = 0; ii < elem_fn_values->no_uvars; ii++)
+	{
+	  if (DECL_NAME (ii_tree)
+	      && !strcmp (IDENTIFIER_POINTER (DECL_NAME (ii_tree)),
+			  elem_fn_values->uniform_vars[ii]))
+	    {
+	      already_found = true;
+	      elem_fn_values->uniform_location[ii] = arg_number;
+	    }
+	}
+      for (ii = 0; ii < elem_fn_values->no_lvars; ii++)
+	{
+	  if (DECL_NAME (ii_tree)
+	      && !strcmp (IDENTIFIER_POINTER (DECL_NAME (ii_tree)),
+			  elem_fn_values->linear_vars[ii]))
+	    {
+	      if (already_found)
+		  fatal_error
+		    ("variable %s defined in both uniform and linear clause",
+		     elem_fn_values->linear_vars[ii]);
+	      else
+		{
+		  already_found = true;
+		  elem_fn_values->linear_location[ii] = arg_number;
+		}
+	    }
+	}
+      if (!already_found) /* This means this variable is a private.  */
+	elem_fn_values->private_location[elem_fn_values->no_pvars++] =
+	  arg_number;
+      arg_number++;
+    }
+
+  elem_fn_values->total_no_args = arg_number;
+  if (elem_fn_values->no_vlengths == 0)
+    /* We have a default value if none is given.  */
+    elem_fn_values->no_vlengths = 1; 
+  return elem_fn_values;
+}
+
+/* This function will check to see if the node is part of an function that
+   needs to be converted to its vector equivalent.  */
+
+bool
+is_elem_fn (tree fndecl)
+{
+  tree ii_tree;
+
+  for (ii_tree = DECL_ATTRIBUTES (fndecl); ii_tree;
+       ii_tree = TREE_CHAIN (ii_tree))
+    {
+      tree ii_value = TREE_PURPOSE (ii_tree);
+      if (TREE_CODE (ii_value) == IDENTIFIER_NODE
+	  && !strcmp (IDENTIFIER_POINTER (ii_value), "vector"))
+	return true;
+    }
+  /* If we are here, then we didn't find a vector keyword, so it is false.  */
+  return false;
+}
diff --git gcc/expr.c gcc/expr.c
index 2ed2f96..f4c6c36 100644
--- gcc/expr.c
+++ gcc/expr.c
@@ -9281,7 +9281,10 @@  expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 	    }
 	  else
 	    pmode = promote_decl_mode (exp, &unsignedp);
-	  gcc_assert (GET_MODE (decl_rtl) == pmode);
+
+	  /* There maybe a pmode rtl for Cilk Plus.  */
+	  if (!flag_enable_cilkplus)
+	    gcc_assert (GET_MODE (decl_rtl) == pmode);
 
 	  temp = gen_lowpart_SUBREG (mode, decl_rtl);
 	  SUBREG_PROMOTED_VAR_P (temp) = 1;
diff --git gcc/function.h gcc/function.h
index 684bbce..8448fe2 100644
--- gcc/function.h
+++ gcc/function.h
@@ -556,6 +556,10 @@  struct GTY(()) function {
   /* Vector of function local variables, functions, types and constants.  */
   VEC(tree,gc) *local_decls;
 
+  /* In an elemental function, if this is true, it means the function is 
+     already cloned, and dont bother cloning it again.  */
+  bool elem_fn_already_cloned;
+
   /* For md files.  */
 
   /* tm.h can use this to store whatever it likes.  */
diff --git gcc/gengtype.c gcc/gengtype.c
index 2ae4372..77dd888 100644
--- gcc/gengtype.c
+++ gcc/gengtype.c
@@ -1646,7 +1646,7 @@  open_base_files (void)
       "tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
       "except.h", "output.h", "gimple.h", "cfgloop.h",
       "target.h", "ipa-prop.h", "lto-streamer.h", "target-globals.h",
-      "ipa-inline.h", "dwarf2out.h", NULL
+      "ipa-inline.h", "cilkplus.h", "dwarf2out.h", NULL
     };
     const char *const *ifp;
     outf_p gtype_desc_c;
diff --git gcc/gimplify.c gcc/gimplify.c
index 0397353..91fbfb9 100644
--- gcc/gimplify.c
+++ gcc/gimplify.c
@@ -47,6 +47,7 @@  along with GCC; see the file COPYING3.  If not see
 
 #include "langhooks-def.h"	/* FIXME: for lhd_set_decl_assembler_name */
 #include "tree-pass.h"		/* FIXME: only for PROP_gimple_any */
+#include "cilkplus.h"
 
 enum gimplify_omp_var_data
 {
@@ -8263,6 +8264,12 @@  gimplify_function_tree (tree fndecl)
 
   oldfn = current_function_decl;
   current_function_decl = fndecl;
+
+  /* Here we check to see if we have a function with the attribute "vector."
+     If so, then we must clone it to masked/unmasked when apropriate.  */
+  if (flag_enable_cilkplus && is_elem_fn (fndecl))
+    lang_hooks.cilkplus.elem_fn_create_fn (fndecl);
+  
   if (DECL_STRUCT_FUNCTION (fndecl))
     push_cfun (DECL_STRUCT_FUNCTION (fndecl));
   else
diff --git gcc/langhooks-def.h gcc/langhooks-def.h
index d8f479f..a27cba9 100644
--- gcc/langhooks-def.h
+++ gcc/langhooks-def.h
@@ -211,6 +211,13 @@  extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
 #define LANG_HOOKS_OMP_FINISH_CLAUSE hook_void_tree
 
+void lhd_elem_fn_create_fn (tree);
+#define LANG_HOOKS_ELEM_FN_CREATE_FN lhd_elem_fn_create_fn
+
+#define LANG_HOOKS_CILKPLUS { \
+  LANG_HOOKS_ELEM_FN_CREATE_FN \
+}
+
 #define LANG_HOOKS_DECLS { \
   LANG_HOOKS_GLOBAL_BINDINGS_P, \
   LANG_HOOKS_PUSHDECL, \
@@ -288,6 +295,7 @@  extern void lhd_end_section (void);
   LANG_HOOKS_TREE_DUMP_INITIALIZER, \
   LANG_HOOKS_DECLS, \
   LANG_HOOKS_FOR_TYPES_INITIALIZER, \
+  LANG_HOOKS_CILKPLUS, \
   LANG_HOOKS_LTO, \
   LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
   LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \
diff --git gcc/langhooks.c gcc/langhooks.c
index a9e60f9..551197f 100644
--- gcc/langhooks.c
+++ gcc/langhooks.c
@@ -667,3 +667,12 @@  lhd_end_section (void)
       saved_section = NULL;
     }
 }
+
+/* Empty function that will always just return for elem fn create fn.  */
+
+void
+lhd_elem_fn_create_fn (tree x ATTRIBUTE_UNUSED)
+{
+    return;
+}
+
diff --git gcc/langhooks.h gcc/langhooks.h
index a919067..ae8764f 100644
--- gcc/langhooks.h
+++ gcc/langhooks.h
@@ -225,6 +225,14 @@  struct lang_hooks_for_decls
   void (*omp_finish_clause) (tree clause);
 };
 
+/* Language hooks related to Cilk Plus, mainly Cilk keywords handling.  */
+
+struct lang_hooks_for_cilkplus
+{ 
+  void (*elem_fn_create_fn) (tree);
+};
+
+
 /* Language hooks related to LTO serialization.  */
 
 struct lang_hooks_for_lto
@@ -406,6 +414,8 @@  struct lang_hooks
 
   struct lang_hooks_for_types types;
 
+  struct lang_hooks_for_cilkplus cilkplus;
+
   struct lang_hooks_for_lto lto;
 
   /* Returns the generic parameters of an instantiation of
diff --git gcc/target.def gcc/target.def
index 0d23c57..bbaca24 100644
--- gcc/target.def
+++ gcc/target.def
@@ -941,6 +941,22 @@  hook_int_uint_mode_1)
 
 HOOK_VECTOR_END (sched)
 
+/* Functions relating to Cilk Plus.  */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_CILKPLUS_"
+HOOK_VECTOR (TARGET_CILKPLUS, cilkplus)
+/* The following member value is a function that is used by Cilk Plus routines
+   to map the processor attribute to the appropriate arch and tune attributes.
+   By default, a NULL string is returned.  */
+DEFHOOK
+(builtin_map_processor_to_attr,
+"This hook is called by a Cilk Plus routine that will be used to map the\n\
+processor clause to the appropriate arch and tune attributes.",
+tree, (char *, tree *),
+default_builtin_map_processor_to_attr)
+
+HOOK_VECTOR_END (cilkplus)
+
 /* Functions relating to vectorization.  */
 #undef HOOK_PREFIX
 #define HOOK_PREFIX "TARGET_VECTORIZE_"
diff --git gcc/targhooks.c gcc/targhooks.c
index 36f998a..9e7d232 100644
--- gcc/targhooks.c
+++ gcc/targhooks.c
@@ -1521,4 +1521,13 @@  default_member_type_forces_blk (const_tree, enum machine_mode)
   return false;
 }
 
+/* Default version of default_builtin_processor_to_arch.  */
+
+tree
+default_builtin_map_processor_to_attr (char *, tree *opp_attr)
+{
+  *opp_attr = NULL_TREE;
+  return NULL_TREE;
+}
+
 #include "gt-targhooks.h"
diff --git gcc/tree-data-ref.c gcc/tree-data-ref.c
index 38327b0..a3a101a 100644
--- gcc/tree-data-ref.c
+++ gcc/tree-data-ref.c
@@ -86,6 +86,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "tree-affine.h"
 #include "params.h"
+#include "cilkplus.h"
 
 static struct datadep_stats
 {
@@ -4383,8 +4384,18 @@  find_data_references_in_stmt (struct loop *nest, gimple stmt,
 
   if (get_references_in_stmt (stmt, &references))
     {
-      VEC_free (data_ref_loc, heap, references);
-      return false;
+      /* If we have an elemental function, then dont worry about its refernce
+	 it is probably available somewhere */
+      if (flag_enable_cilkplus
+	  && gimple_code (stmt) == GIMPLE_CALL
+	  && gimple_call_fndecl (stmt)
+	  && is_elem_fn (gimple_call_fndecl (stmt)))
+	;
+      else
+	{
+	  VEC_free (data_ref_loc, heap, references);
+	  return false;
+	}
     }
 
   FOR_EACH_VEC_ELT (data_ref_loc, references, i, ref)
diff --git gcc/tree-inline.c gcc/tree-inline.c
index 05f271f..6ab3d11 100644
--- gcc/tree-inline.c
+++ gcc/tree-inline.c
@@ -4867,6 +4867,68 @@  copy_arguments_for_versioning (tree orig_parm, copy_body_data * id,
   return new_parm;
 }
 
+/* Return a copy of the function's argument tree.  */
+
+static tree
+elem_fn_copy_arguments_for_versioning (tree orig_parm, copy_body_data * id,
+				       bitmap args_to_skip, tree *vars,
+				       int vlength, bool masked)
+{
+  tree arg, *parg;
+  tree new_parm = NULL;
+  int i = 0;
+  tree masked_parm = NULL_TREE;
+  parg = &new_parm;
+
+  if (masked)
+    {
+      masked_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL,
+				get_identifier ("__elem_fn_mask"),
+				build_vector_type (integer_type_node, vlength));
+      DECL_ARG_TYPE (masked_parm) = build_vector_type (integer_type_node,
+						       vlength);
+      DECL_ARTIFICIAL (masked_parm) = 1;
+      lang_hooks.dup_lang_specific_decl (masked_parm);
+    }
+  for (arg = orig_parm; arg; arg = DECL_CHAIN (arg), i++)
+    if (!args_to_skip || !bitmap_bit_p (args_to_skip, i))
+      {
+        tree new_tree = remap_decl (arg, id);
+	if (TREE_CODE (new_tree) != PARM_DECL)
+	  new_tree = id->copy_decl (arg, id);
+	TREE_TYPE (new_tree) = copy_node (TREE_TYPE (new_tree));
+	TREE_TYPE (new_tree) = build_vector_type (TREE_TYPE (new_tree),
+						  vlength);
+	DECL_ARG_TYPE (new_tree) = build_vector_type (DECL_ARG_TYPE (new_tree),
+						      vlength);
+        lang_hooks.dup_lang_specific_decl (new_tree);
+        *parg = new_tree;
+	parg = &DECL_CHAIN (new_tree);
+      }
+    else if (!pointer_map_contains (id->decl_map, arg))
+      {
+	/* Make an equivalent VAR_DECL.  If the argument was used
+	   as temporary variable later in function, the uses will be
+	   replaced by local variable.  */
+	tree var = copy_decl_to_var (arg, id);
+	insert_decl_map (id, arg, var);
+        /* Declare this new variable.  */
+        DECL_CHAIN (var) = *vars;
+        *vars = var;
+      }
+  if (masked && masked_parm)
+    {
+      for (arg = new_parm; DECL_CHAIN (arg); arg = DECL_CHAIN(arg))
+	;
+      
+      DECL_CONTEXT (masked_parm) = DECL_CONTEXT (arg);
+      DECL_CHAIN (arg) = masked_parm;
+    }
+  return new_parm;
+}
+
+
+
 /* Return a copy of the function's static chain.  */
 static tree
 copy_static_chain (tree static_chain, copy_body_data * id)
@@ -5267,6 +5329,250 @@  tree_function_versioning (tree old_decl, tree new_decl,
   return;
 }
 
+/* This function initializes the cfun struct for elemental functions.  */
+
+static void
+initialize_elem_fn_cfun (tree new_fndecl, tree callee_fndecl)
+{
+  struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);
+
+  /* Get clean struct function.  */
+  push_struct_function (new_fndecl);
+
+  /* We will rebuild these, so just sanity check that they are empty.  */
+  gcc_assert (VALUE_HISTOGRAMS (cfun) == NULL);
+  gcc_assert (cfun->local_decls == NULL);
+  gcc_assert (cfun->cfg == NULL);
+  gcc_assert (cfun->decl == new_fndecl);
+
+  /* Copy items we preserve during cloning.  */
+  cfun->static_chain_decl = src_cfun->static_chain_decl;
+  cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area;
+  cfun->function_end_locus = src_cfun->function_end_locus;
+  cfun->curr_properties = src_cfun->curr_properties & ~PROP_loops;
+  cfun->last_verified = src_cfun->last_verified;
+  cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
+  cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
+  cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
+  cfun->stdarg = src_cfun->stdarg;
+  cfun->after_inlining = src_cfun->after_inlining;
+  cfun->can_throw_non_call_exceptions
+    = src_cfun->can_throw_non_call_exceptions;
+  cfun->returns_struct = src_cfun->returns_struct;
+  cfun->returns_pcc_struct = src_cfun->returns_pcc_struct;
+  
+  if (src_cfun->eh)
+    init_eh_for_function ();
+
+  if (src_cfun->gimple_df)
+    {
+      init_tree_ssa (cfun);
+      cfun->gimple_df->in_ssa_p = true;
+      init_ssa_operands (cfun);
+    }
+  pop_cfun ();
+}
+
+/* Elemental fucntion's version of tree_versioning.  */
+
+void
+tree_elem_fn_versioning (tree old_decl, tree new_decl,
+			 VEC(ipa_replace_map_p,gc)* tree_map,
+			 bool update_clones, bitmap args_to_skip,
+			 bool skip_return,
+			 bitmap blocks_to_copy ATTRIBUTE_UNUSED,
+			 basic_block new_entry ATTRIBUTE_UNUSED, int vlength,
+			 bool masked)
+{
+  copy_body_data id;
+  tree p;
+  unsigned i;
+  struct ipa_replace_map *replace_info;
+  VEC (gimple, heap) *init_stmts = VEC_alloc (gimple, heap, 10);
+
+  tree old_current_function_decl = current_function_decl;
+  tree vars = NULL_TREE;
+
+  gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL
+	      && TREE_CODE (new_decl) == FUNCTION_DECL);
+  DECL_POSSIBLY_INLINED (old_decl) = 1;
+  
+  /* Copy over debug args.  */
+  if (DECL_HAS_DEBUG_ARGS_P (old_decl))
+    {
+      VEC(tree, gc) **new_debug_args, **old_debug_args;
+      gcc_checking_assert (decl_debug_args_lookup (new_decl) == NULL);
+      DECL_HAS_DEBUG_ARGS_P (new_decl) = 0;
+      old_debug_args = decl_debug_args_lookup (old_decl);
+      if (old_debug_args)
+	{
+	  new_debug_args = decl_debug_args_insert (new_decl);
+	  *new_debug_args = VEC_copy (tree, gc, *old_debug_args);
+	}
+    }
+
+  /* Output the inlining info for this abstract function, since it has been
+     inlined.  If we don't do this now, we can lose the information about the
+     variables in the function when the blocks get blown away as soon as we
+     remove the cgraph node.  */
+  (*debug_hooks->outlining_inline_function) (old_decl);
+
+  DECL_ARTIFICIAL (new_decl) = 1;
+  /* Prepare the data structures for the tree copy.  */
+  memset (&id, 0, sizeof (id));
+
+  /* Generate a new name for the new version. */
+  id.statements_to_fold = pointer_set_create ();
+
+  id.decl_map = pointer_map_create ();
+  id.debug_map = NULL;
+  id.src_fn = old_decl;
+  id.dst_fn = new_decl;
+  id.src_node = NULL;
+  id.dst_node = NULL;
+  id.src_cfun = DECL_STRUCT_FUNCTION (old_decl);
+
+  id.copy_decl = copy_decl_no_change;
+  id.transform_call_graph_edges
+    = update_clones ? CB_CGE_MOVE_CLONES : CB_CGE_MOVE;
+  id.transform_new_cfg = true;
+  id.transform_return_to_modify = false;
+  id.transform_lang_insert_block = NULL;
+
+  current_function_decl = new_decl;
+  
+  initialize_elem_fn_cfun (new_decl, old_decl);
+  push_cfun (DECL_STRUCT_FUNCTION (new_decl));
+
+  /* Copy the function's static chain.  */
+  p = DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl;
+  if (p)
+    DECL_STRUCT_FUNCTION (new_decl)->static_chain_decl =
+      copy_static_chain (DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl,
+			 &id);
+
+  /* If there's a tree_map, prepare for substitution.  */
+  if (tree_map)
+    for (i = 0; i < VEC_length (ipa_replace_map_p, tree_map); i++)
+      {
+	gimple init;
+	replace_info = VEC_index (ipa_replace_map_p, tree_map, i);
+	if (replace_info->replace_p)
+	  {
+	    tree op = replace_info->new_tree;
+	    if (!replace_info->old_tree)
+	      {
+		int i = replace_info->parm_num;
+		tree parm;
+		for (parm = DECL_ARGUMENTS (old_decl); i;
+		     parm = DECL_CHAIN (parm))
+		  i --;
+		replace_info->old_tree = parm;
+	      }
+		
+
+	    STRIP_NOPS (op);
+
+	    if (TREE_CODE (op) == VIEW_CONVERT_EXPR)
+	      op = TREE_OPERAND (op, 0);
+      
+	    gcc_assert (TREE_CODE (replace_info->old_tree) == PARM_DECL);
+	    init = setup_one_parameter (&id, replace_info->old_tree,
+	    			        replace_info->new_tree, id.src_fn,
+				        NULL,
+				        &vars);
+	    if (init)
+	      VEC_safe_push (gimple, heap, init_stmts, init);
+	  }
+      }
+  /* Copy the function's arguments.  */
+  if (DECL_ARGUMENTS (old_decl) != NULL_TREE)
+    DECL_ARGUMENTS (new_decl) =
+      elem_fn_copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id,
+					     args_to_skip, &vars,
+					     vlength, masked);
+
+  DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
+  BLOCK_SUPERCONTEXT (DECL_INITIAL (new_decl)) = new_decl;
+
+  declare_inline_vars (DECL_INITIAL (new_decl), vars);
+
+  if (!VEC_empty (tree, DECL_STRUCT_FUNCTION (old_decl)->local_decls))
+    /* Add local vars.  */
+    add_local_variables (DECL_STRUCT_FUNCTION (old_decl), cfun, &id);
+
+  if (DECL_RESULT (old_decl) == NULL_TREE)
+    ;
+  else if (skip_return && !VOID_TYPE_P (TREE_TYPE (DECL_RESULT (old_decl))))
+    {
+      DECL_RESULT (new_decl)
+	= build_decl (DECL_SOURCE_LOCATION (DECL_RESULT (old_decl)),
+		      RESULT_DECL, NULL_TREE, void_type_node);
+      DECL_CONTEXT (DECL_RESULT (new_decl)) = new_decl;
+      cfun->returns_struct = 0;
+      cfun->returns_pcc_struct = 0;
+    }
+  else
+    {
+      tree old_name;
+      DECL_RESULT (new_decl) = remap_decl (DECL_RESULT (old_decl), &id);
+      if (TREE_TYPE (DECL_RESULT (new_decl)) != void_type_node)
+	{
+	  TREE_TYPE (DECL_RESULT (new_decl)) =
+	    build_vector_type (copy_node (TREE_TYPE (DECL_RESULT (new_decl))),
+			       vlength);
+	  DECL_MODE (DECL_RESULT (new_decl)) =
+	    TYPE_MODE (TREE_TYPE (DECL_RESULT (new_decl)));
+	}
+      if (TREE_TYPE (TREE_TYPE (old_decl)) != void_type_node)
+	{
+	  TREE_TYPE (new_decl) = copy_node (TREE_TYPE (old_decl));
+	  TREE_TYPE (TREE_TYPE (new_decl)) =
+	    copy_node (TREE_TYPE (TREE_TYPE (old_decl)));
+	  TREE_TYPE (TREE_TYPE (new_decl)) =
+	    build_vector_type (TREE_TYPE (TREE_TYPE (new_decl)), vlength);
+	}
+      lang_hooks.dup_lang_specific_decl (DECL_RESULT (new_decl));
+      if (gimple_in_ssa_p (id.src_cfun)
+	  && DECL_BY_REFERENCE (DECL_RESULT (old_decl))
+	  && (old_name = ssa_default_def (id.src_cfun, DECL_RESULT (old_decl))))
+	{
+	  tree new_name = make_ssa_name (DECL_RESULT (new_decl), NULL);
+	  insert_decl_map (&id, old_name, new_name);
+	  SSA_NAME_DEF_STMT (new_name) = gimple_build_nop ();
+	  set_ssa_default_def (cfun, DECL_RESULT (new_decl), new_name);
+	}
+    }
+  walk_tree (&DECL_SAVED_TREE (new_decl), copy_tree_body_r, &id, NULL);
+  /* Renumber the lexical scoping (non-code) blocks consecutively.  */
+  number_blocks (new_decl);
+
+  
+  /* Remap the nonlocal_goto_save_area, if any.  */
+  if (cfun->nonlocal_goto_save_area)
+    {
+      struct walk_stmt_info wi;
+
+      memset (&wi, 0, sizeof (wi));
+      wi.info = &id;
+      walk_tree (&cfun->nonlocal_goto_save_area, remap_gimple_op_r, &wi, NULL);
+    }
+  
+  /* Clean up.  */
+  pointer_map_destroy (id.decl_map);
+  if (id.debug_map)
+    pointer_map_destroy (id.debug_map);
+
+  gcc_assert (!id.debug_stmts);
+  VEC_free (gimple, heap, init_stmts);
+  pop_cfun ();
+  current_function_decl = old_current_function_decl;
+  gcc_assert (!current_function_decl
+	      || DECL_STRUCT_FUNCTION (current_function_decl) == cfun);
+  return;
+}
+
+
 /* EXP is CALL_EXPR present in a GENERIC expression tree.  Try to integrate
    the callee and return the inlined body on success.  */
 
diff --git gcc/tree-vect-stmts.c gcc/tree-vect-stmts.c
index ab4a26c..93c359e 100644
--- gcc/tree-vect-stmts.c
+++ gcc/tree-vect-stmts.c
@@ -40,9 +40,13 @@  along with GCC; see the file COPYING3.  If not see
 
 /* For lang_hooks.types.type_for_mode.  */
 #include "langhooks.h"
+#include "cilkplus.h"
 
-/* Return the vectorized type for the given statement.  */
+tree elem_fn_linear_init_vector (gimple stmt, tree val, tree type, 
+				 tree step_size, gimple_stmt_iterator *gsi);
+extern enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree, tree *);
 
+/* Return the vectorized type for the given statement.  */
 tree
 stmt_vectype (struct _stmt_vec_info *stmt_info)
 {
@@ -1316,6 +1320,8 @@  vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
   enum vect_def_type dt;
   bool is_simple_use;
   tree vector_type;
+  enum elem_fn_parm_type parm_type;
+  tree step_size = NULL_TREE;
 
   if (vect_print_dump_info (REPORT_DETAILS))
     {
@@ -1340,13 +1346,24 @@  vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
         }
     }
 
+  if (flag_enable_cilkplus
+      && gimple_code (stmt) == GIMPLE_CALL
+      && is_elem_fn (gimple_call_fndecl (stmt)))
+    {
+      parm_type = find_elem_fn_parm_type (stmt, op, &step_size);
+      if (parm_type == TYPE_UNIFORM || parm_type == TYPE_LINEAR)
+	dt = vect_external_def;
+    }
+  else
+    parm_type = TYPE_NONE;
+      
   switch (dt)
     {
     /* Case 1: operand is a constant.  */
     case vect_constant_def:
       {
 	vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
-	gcc_assert (vector_type);
+	gcc_assert (vector_type);  
 	nunits = TYPE_VECTOR_SUBPARTS (vector_type);
 
 	if (scalar_def)
@@ -1355,8 +1372,13 @@  vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
         /* Create 'vect_cst_ = {cst,cst,...,cst}'  */
         if (vect_print_dump_info (REPORT_DETAILS))
           fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
-
-        return vect_init_vector (stmt, op, vector_type, NULL);
+	if (!flag_enable_cilkplus 
+	    || (parm_type == TYPE_NONE || parm_type == TYPE_UNIFORM))
+	  return vect_init_vector (stmt, op, vector_type, NULL);
+	else if (flag_enable_cilkplus && parm_type == TYPE_LINEAR)
+	  return elem_fn_linear_init_vector (stmt, op, vector_type,
+					     step_size, NULL);
+					     
       }
 
     /* Case 2: operand is defined outside the loop - loop invariant.  */
@@ -1371,8 +1393,185 @@  vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
         /* Create 'vec_inv = {inv,inv,..,inv}'  */
         if (vect_print_dump_info (REPORT_DETAILS))
           fprintf (vect_dump, "Create vector_inv.");
+	if (!flag_enable_cilkplus
+	    || (parm_type == TYPE_NONE || parm_type == TYPE_UNIFORM))
+	  return vect_init_vector (stmt, op, vector_type, NULL);
+	else if (flag_enable_cilkplus && parm_type == TYPE_LINEAR)
+	  return elem_fn_linear_init_vector (stmt, op, vector_type,
+					     step_size, NULL);
+      }
 
-        return vect_init_vector (stmt, def, vector_type, NULL);
+    /* Case 3: operand is defined inside the loop.  */
+    case vect_internal_def:
+      {
+	if (scalar_def)
+	  *scalar_def = NULL/* FIXME tuples: def_stmt*/;
+
+        /* Get the def from the vectorized stmt.  */
+        def_stmt_info = vinfo_for_stmt (def_stmt);
+
+        vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
+        /* Get vectorized pattern statement.  */
+        if (!vec_stmt
+            && STMT_VINFO_IN_PATTERN_P (def_stmt_info)
+            && !STMT_VINFO_RELEVANT (def_stmt_info))
+          vec_stmt = STMT_VINFO_VEC_STMT (vinfo_for_stmt (
+                       STMT_VINFO_RELATED_STMT (def_stmt_info)));
+        gcc_assert (vec_stmt);
+	if (gimple_code (vec_stmt) == GIMPLE_PHI)
+	  vec_oprnd = PHI_RESULT (vec_stmt);
+	else if (is_gimple_call (vec_stmt))
+	  vec_oprnd = gimple_call_lhs (vec_stmt);
+	else
+	  vec_oprnd = gimple_assign_lhs (vec_stmt);
+        return vec_oprnd;
+      }
+
+    /* Case 4: operand is defined by a loop header phi - reduction  */
+    case vect_reduction_def:
+    case vect_double_reduction_def:
+    case vect_nested_cycle:
+      {
+	struct loop *loop;
+
+	gcc_assert (gimple_code (def_stmt) == GIMPLE_PHI);
+	loop = (gimple_bb (def_stmt))->loop_father;
+
+        /* Get the def before the loop  */
+        op = PHI_ARG_DEF_FROM_EDGE (def_stmt, loop_preheader_edge (loop));
+        return get_initial_def_for_reduction (stmt, op, scalar_def);
+     }
+
+    /* Case 5: operand is defined by loop-header phi - induction.  */
+    case vect_induction_def:
+      {
+	gcc_assert (gimple_code (def_stmt) == GIMPLE_PHI);
+
+        /* Get the def from the vectorized stmt.  */
+        def_stmt_info = vinfo_for_stmt (def_stmt);
+        vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
+	if (gimple_code (vec_stmt) == GIMPLE_PHI)
+	  vec_oprnd = PHI_RESULT (vec_stmt);
+	else
+	  vec_oprnd = gimple_get_lhs (vec_stmt);
+        return vec_oprnd;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+
+/* Function elem_fn_vect_get_vec_def_for_operand.
+
+   OP is an operand in STMT.  This function returns a (vector) def that will be
+   used in the vectorized stmt for STMT.
+
+   In the case that OP is an SSA_NAME which is defined in the loop, then
+   STMT_VINFO_VEC_STMT of the defining stmt holds the relevant def.
+
+   In case OP is an invariant or constant, a new stmt that creates a vector def
+   needs to be introduced.  */
+
+tree
+elem_fn_vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def,
+				      gimple_stmt_iterator *gsi)
+{
+  tree vec_oprnd;
+  gimple vec_stmt;
+  gimple def_stmt;
+  stmt_vec_info def_stmt_info = NULL;
+  stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
+  unsigned int nunits;
+  loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+  tree def;
+  enum vect_def_type dt;
+  bool is_simple_use;
+  tree vector_type;
+  enum elem_fn_parm_type parm_type;
+  tree step_size = NULL_TREE;
+
+  if (vect_print_dump_info (REPORT_DETAILS))
+    {
+      fprintf (vect_dump, "elem_fn_vect_get_vec_def_for_operand: ");
+      print_generic_expr (vect_dump, op, TDF_SLIM);
+    }
+
+  is_simple_use = vect_is_simple_use (op, stmt, loop_vinfo, NULL,
+				      &def_stmt, &def, &dt);
+  gcc_assert (is_simple_use);
+  if (vect_print_dump_info (REPORT_DETAILS))
+    {
+      if (def)
+        {
+          fprintf (vect_dump, "def =  ");
+          print_generic_expr (vect_dump, def, TDF_SLIM);
+        }
+      if (def_stmt)
+        {
+          fprintf (vect_dump, "  def_stmt =  ");
+	  print_gimple_stmt (vect_dump, def_stmt, 0, TDF_SLIM);
+        }
+    }
+
+  if (flag_enable_cilkplus
+      && gimple_code (stmt) == GIMPLE_CALL
+      && is_elem_fn (gimple_call_fndecl (stmt)))
+    {
+      parm_type = find_elem_fn_parm_type (stmt, op, &step_size);
+      if (parm_type == TYPE_UNIFORM || parm_type == TYPE_LINEAR)
+	dt = vect_external_def;
+    }
+  else
+    parm_type = TYPE_NONE;
+      
+  switch (dt)
+    {
+    /* Case 1: operand is a constant.  */
+    case vect_constant_def:
+      {
+	vector_type = get_vectype_for_scalar_type (TREE_TYPE (op));
+	gcc_assert (vector_type);  
+	nunits = TYPE_VECTOR_SUBPARTS (vector_type);
+
+	if (scalar_def)
+	  *scalar_def = op;
+
+        /* Create 'vect_cst_ = {cst,cst,...,cst}'  */
+        if (vect_print_dump_info (REPORT_DETAILS))
+          fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
+	if (!flag_enable_cilkplus)
+	  return vect_init_vector (stmt, op, vector_type, NULL);
+	else if (flag_enable_cilkplus
+		 && (parm_type == TYPE_UNIFORM || parm_type == TYPE_NONE))
+	  return vect_init_vector (stmt, op, vector_type, gsi);
+	else if (flag_enable_cilkplus && parm_type == TYPE_LINEAR)
+	  return elem_fn_linear_init_vector (stmt, op, vector_type,
+					     step_size, gsi);
+				     
+      }
+
+    /* Case 2: operand is defined outside the loop - loop invariant.  */
+    case vect_external_def:
+      {
+	vector_type = get_vectype_for_scalar_type (TREE_TYPE (def));
+	gcc_assert (vector_type);
+
+	if (scalar_def)
+	  *scalar_def = def;
+
+        /* Create 'vec_inv = {inv,inv,..,inv}'  */
+        if (vect_print_dump_info (REPORT_DETAILS))
+          fprintf (vect_dump, "Create vector_inv.");
+	if (!flag_enable_cilkplus)
+	  return vect_init_vector (stmt, op, vector_type, NULL);
+	else if (flag_enable_cilkplus
+		 && (parm_type == TYPE_UNIFORM || parm_type == TYPE_NONE))
+	  return vect_init_vector (stmt, op, vector_type, gsi);
+	else if (flag_enable_cilkplus && parm_type == TYPE_LINEAR)
+	  return elem_fn_linear_init_vector (stmt, op, vector_type, step_size,
+					     gsi);
       }
 
     /* Case 3: operand is defined inside the loop.  */
@@ -1620,9 +1819,17 @@  vect_finish_stmt_generation (gimple stmt, gimple vec_stmt,
 		      && !(gimple_call_flags (vec_stmt)
 			   & (ECF_CONST|ECF_PURE|ECF_NOVOPS)))))
 	    {
-	      tree new_vdef = copy_ssa_name (vuse, vec_stmt);
-	      gimple_set_vdef (vec_stmt, new_vdef);
-	      SET_USE (gimple_vuse_op (at_stmt), new_vdef);
+	      /* Elemental functions are removed and inserted seperately.  So,
+		 we do not add any use information for them at this point.  */
+	      if (flag_enable_cilkplus && is_gimple_call (stmt)
+		  && is_elem_fn (gimple_call_fndecl (stmt)))
+		;
+	      else
+		{
+		  tree new_vdef = copy_ssa_name (vuse, vec_stmt);
+		  gimple_set_vdef (vec_stmt, new_vdef);
+		  SET_USE (gimple_vuse_op (at_stmt), new_vdef);
+		}
 	    }
 	}
     }
@@ -1649,6 +1856,19 @@  vectorizable_function (gimple call, tree vectype_out, tree vectype_in)
 {
   tree fndecl = gimple_call_fndecl (call);
 
+  if (flag_enable_cilkplus && is_elem_fn (fndecl))
+    {
+      if (DECL_ELEM_FN_ALREADY_CLONED (fndecl))
+	return fndecl;
+      else
+	{
+	  tree new_fndecl = find_elem_fn_name (copy_node (fndecl),
+					       vectype_out, vectype_in);
+	  if (new_fndecl)
+	    DECL_ELEM_FN_ALREADY_CLONED (new_fndecl) = 1;
+	  return new_fndecl;
+	}
+    }
   /* We only handle functions that do not read or clobber memory -- i.e.
      const or novops ones.  */
   if (!(gimple_call_flags (call) & (ECF_CONST | ECF_NOVOPS)))
@@ -1694,6 +1914,7 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   enum { NARROW, NONE, WIDEN } modifier;
   size_t i, nargs;
   tree lhs;
+  tree step_size = NULL_TREE;
 
   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
     return false;
@@ -1721,7 +1942,7 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   /* Bail out if the function has more than three arguments, we do not have
      interesting builtin functions to vectorize with more than two arguments
      except for fma.  No arguments is also not good.  */
-  if (nargs == 0 || nargs > 3)
+  if (!flag_enable_cilkplus && (nargs == 0 || nargs > 3))
     return false;
 
   for (i = 0; i < nargs; i++)
@@ -1801,8 +2022,6 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
       return false;
     }
 
-  gcc_assert (!gimple_vuse (stmt));
-
   if (slp_node || PURE_SLP_STMT (stmt_info))
     ncopies = 1;
   else if (modifier == NARROW)
@@ -1891,11 +2110,28 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	    {
 	      op = gimple_call_arg (stmt, i);
 	      if (j == 0)
-		vec_oprnd0
-		  = vect_get_vec_def_for_operand (op, stmt, NULL);
+		{
+		  if (flag_enable_cilkplus)
+		    vec_oprnd0
+		      = elem_fn_vect_get_vec_def_for_operand (op, stmt, NULL,
+							      gsi);
+		  else
+		    vec_oprnd0
+		      = vect_get_vec_def_for_operand (op, stmt, NULL);
+		}
 	      else
 		{
 		  vec_oprnd0 = gimple_call_arg (new_stmt, i);
+		  if (flag_enable_cilkplus
+		      && gimple_code (new_stmt) == GIMPLE_CALL
+		      && is_elem_fn (gimple_call_fndecl (new_stmt)))
+		    {
+		      enum elem_fn_parm_type parm_type =
+			find_elem_fn_parm_type (stmt, op, &step_size);
+		      if (parm_type == TYPE_UNIFORM
+			  || parm_type == TYPE_LINEAR)
+			dt[i] = vect_constant_def;
+		    }
 		  vec_oprnd0
                     = vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
 		}
@@ -1906,6 +2142,8 @@  vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  new_stmt = gimple_build_call_vec (fndecl, vargs);
 	  new_temp = make_ssa_name (vec_dest, new_stmt);
 	  gimple_call_set_lhs (new_stmt, new_temp);
+	  if (flag_enable_cilkplus && is_elem_fn (fndecl))
+	    gimple_call_set_fntype (new_stmt, TREE_TYPE (fndecl));
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
 	  if (j == 0)
@@ -6592,3 +6830,45 @@  supportable_narrowing_operation (enum tree_code code,
   VEC_free (tree, heap, *interm_types);
   return false;
 }
+
+/* Elemental function's version of vect_init_vector.  */
+
+tree
+elem_fn_linear_init_vector (gimple stmt, tree val, tree type, tree step_size,
+			    gimple_stmt_iterator *gsi)
+{
+  tree new_var;
+  gimple init_stmt;
+  tree vec_oprnd;
+  tree new_temp;
+
+  if (TREE_CODE (type) == VECTOR_TYPE
+      && TREE_CODE (TREE_TYPE (val)) != VECTOR_TYPE)
+    {
+      if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
+	{
+	  if (CONSTANT_CLASS_P (val))
+	    val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+	  else
+	    {
+	      new_var = create_tmp_reg (TREE_TYPE (type), NULL);
+	      init_stmt = gimple_build_assign_with_ops (NOP_EXPR,
+							new_var, val,
+							NULL_TREE);
+	      new_temp = make_ssa_name (new_var, init_stmt);
+	      gimple_assign_set_lhs (init_stmt, new_temp);
+	      vect_init_vector_1 (stmt, init_stmt, gsi);
+	      val = new_temp;
+	    }
+	}
+      val = build_elem_fn_linear_vector_from_val (type, val, step_size);
+    }
+
+  new_var = vect_get_new_vect_var (type, vect_simple_var, "cst_");
+  init_stmt = gimple_build_assign  (new_var, val);
+  new_temp = make_ssa_name (new_var, init_stmt);
+  gimple_assign_set_lhs (init_stmt, new_temp);
+  vect_init_vector_1 (stmt, init_stmt, gsi);
+  vec_oprnd = gimple_assign_lhs (init_stmt);
+  return vec_oprnd;
+}
diff --git gcc/tree.c gcc/tree.c
index 469f473..fb18648 100644
--- gcc/tree.c
+++ gcc/tree.c
@@ -1405,6 +1405,54 @@  build_vector_from_val (tree vectype, tree sc)
     }
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  This is
+   a specialized version for elemental functions.  */
+
+tree
+build_elem_fn_linear_vector_from_val (tree vectype, tree sc, tree step_size)
+{
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+  if (sc == error_mark_node)
+    return sc;
+
+  /* Verify that the vector type is suitable for SC.  Note that there
+     is some inconsistency in the type-system with respect to restrict
+     qualifications of pointers.  Vector types always have a main-variant
+     element type and the qualification is applied to the vector-type.
+     So TREE_TYPE (vector-type) does not return a properly qualified
+     vector element-type.  */
+  gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)),
+					   TREE_TYPE (vectype)));
+
+  if (CONSTANT_CLASS_P (sc))
+    {
+      tree *v = XALLOCAVEC (tree, nunits);
+      for (i = 0; i < nunits; ++i)
+	// v[i] = sc;
+	v[i] = build2 (PLUS_EXPR, TREE_TYPE (sc), sc,
+		       fold_build2 (MULT_EXPR, TREE_TYPE (step_size), step_size,
+				    build_int_cst (integer_type_node, i)));
+      return build_vector (vectype, v);
+    }
+  else
+    {
+      VEC(constructor_elt, gc) *v = VEC_alloc (constructor_elt, gc, nunits);
+      for (i = 0; i < nunits; ++i)
+	{
+	  // CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
+	  tree tmp = NULL_TREE;
+	  tmp = build2 (PLUS_EXPR, TREE_TYPE (sc), sc,
+			fold_build2 (MULT_EXPR, TREE_TYPE (step_size),
+				     step_size,
+				     build_int_cst (integer_type_node, i)));
+	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tmp);
+	}
+      return build_constructor (vectype, v);
+    }
+}
+
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
diff --git gcc/tree.h gcc/tree.h
index d81aa3c..268fd8b 100644
--- gcc/tree.h
+++ gcc/tree.h
@@ -3460,6 +3460,12 @@  extern VEC(tree, gc) **decl_debug_args_insert (tree);
 #define DECL_FUNCTION_SPECIFIC_OPTIMIZATION(NODE) \
    (FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_optimization)
 
+/* In FUNCTION_DECL, this bit is set to indicate that the function is already
+   cloned and there is no need to attempt to do it again.  This mainly stops
+   infinite cloning.  */
+#define DECL_ELEM_FN_ALREADY_CLONED(NODE) \
+    (FUNCTION_DECL_CHECK (NODE)->function_decl.elem_fn_already_cloned)
+
 /* FUNCTION_DECL inherits from DECL_NON_COMMON because of the use of the
    arguments/result/saved_tree fields by front ends.   It was either inherit
    FUNCTION_DECL from non_common, or inherit non_common from FUNCTION_DECL,
@@ -3504,8 +3510,8 @@  struct GTY(()) tree_function_decl {
   unsigned looping_const_or_pure_flag : 1;
   unsigned has_debug_args_flag : 1;
   unsigned tm_clone_flag : 1;
+  unsigned elem_fn_already_cloned : 1;
 
-  /* 1 bit left */
 };
 
 /* The source language of the translation-unit.  */
@@ -4730,6 +4736,7 @@  extern tree build_vector_stat (tree, tree * MEM_STAT_DECL);
 #define build_vector(t,v) build_vector_stat (t, v MEM_STAT_INFO)
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
 extern tree build_vector_from_val (tree, tree);
+extern tree build_elem_fn_linear_vector_from_val (tree, tree, tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);