diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f696913e03814687c66c396f3218b30efe4c6fe..1215863c452b462b92b5293ec4f85bc83fed3909 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2009-03-30  Martin Jambor  <mjambor@suse.cz>
+
+	* ipa-prop.h (jump_func_type): Rename IPA_UNKNOWN, IPA_CONST,
+	IPA_CONST_MEMBER_PTR, and IPA_PASS_THROUGH to IPA_JF_UNKNOWN,
+	IPA_JF_CONST, IPA_JF_CONST_MEMBER_PTR, and IPA_JF_PASS_THROUGH
+	respectively.
+
+	* tree-dfa.c (get_ref_base_and_extent): Return -1 maxsize if
+	seen_variable_array_ref while also traversing a union.
+
+	* tree-inline.c (optimize_inline_calls): Do not call
+	cgraph_node_remove_callees.
+	* cgraphbuild.c (remove_cgraph_callee_edges): New function.
+	(pass_remove_cgraph_callee_edges): New variable.
+	* passes.c (init_optimization_passes): Add
+	pass_remove_cgraph_callee_edges after early inlining and before all
+	late intraprocedural passes.
+
+	* omp-low.c (expand_omp_taskreg): Always set current_function_decl.
+
 2009-03-30  Paolo Bonzini  <bonzini@gnu.org>
 
 	* config/sparc/sparc.md (*nand<V64mode>_vis, *nand<V32mode>_vis):
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 3868712b3f7a819148e0106cef9206eba762269b..c7d6aa72329729f54aca21fe69ec5d2b5d9e7c82 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -251,3 +251,30 @@ struct gimple_opt_pass pass_rebuild_cgraph_edges =
   0,					/* todo_flags_finish */
  }
 };
+
+
+static unsigned int
+remove_cgraph_callee_edges (void)
+{
+  cgraph_node_remove_callees (cgraph_node (current_function_decl));
+  return 0;
+}
+
+struct gimple_opt_pass pass_remove_cgraph_callee_edges =
+{
+ {
+  GIMPLE_PASS,
+  NULL,					/* name */
+  NULL,					/* gate */
+  remove_cgraph_callee_edges,		/* execute */
+  NULL,					/* sub */
+  NULL,					/* next */
+  0,					/* static_pass_number */
+  0,					/* tv_id */
+  0,					/* properties_required */
+  0,					/* properties_provided */
+  0,					/* properties_destroyed */
+  0,					/* todo_flags_start */
+  0,					/* todo_flags_finish */
+ }
+};
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index f6864bb43fa89a5085f19901a3ab4661efda15e4..3fae0297a7886371d4981b77955349befc0152d1 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -310,12 +310,12 @@ static void
 ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
 			 struct ipa_jump_func *jfunc)
 {
-  if (jfunc->type == IPA_CONST)
+  if (jfunc->type == IPA_JF_CONST)
     {
       lat->type = IPA_CONST_VALUE;
       lat->constant = jfunc->value.constant;
     }
-  else if (jfunc->type == IPA_PASS_THROUGH)
+  else if (jfunc->type == IPA_JF_PASS_THROUGH)
     {
       struct ipcp_lattice *caller_lat;
 
@@ -916,7 +916,7 @@ ipcp_need_redirect_p (struct cgraph_edge *cs)
       if (ipcp_lat_is_const (lat))
 	{
 	  jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
-	  if (jump_func->type != IPA_CONST)
+	  if (jump_func->type != IPA_JF_CONST)
 	    return true;
 	}
     }
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index c8db7d2bcd6b7b1267649f2e843ceca328932610..eab3aa7249a8dd4b95350957a09b8375055856e0 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -293,16 +293,16 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
 	  type = jump_func->type;
 
 	  fprintf (f, "       param %d: ", i);
-	  if (type == IPA_UNKNOWN)
+	  if (type == IPA_JF_UNKNOWN)
 	    fprintf (f, "UNKNOWN\n");
-	  else if (type == IPA_CONST)
+	  else if (type == IPA_JF_CONST)
  	    {
 	      tree val = jump_func->value.constant;
 	      fprintf (f, "CONST: ");
 	      print_generic_expr (f, val, 0);
 	      fprintf (f, "\n");
 	    }
-	  else if (type == IPA_CONST_MEMBER_PTR)
+	  else if (type == IPA_JF_CONST_MEMBER_PTR)
 	    {
 	      fprintf (f, "CONST MEMBER PTR: ");
 	      print_generic_expr (f, jump_func->value.member_cst.pfn, 0);
@@ -310,7 +310,7 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
 	      print_generic_expr (f, jump_func->value.member_cst.delta, 0);
 	      fprintf (f, "\n");
 	    }
-	  else if (type == IPA_PASS_THROUGH)
+	  else if (type == IPA_JF_PASS_THROUGH)
  	    {
 	      fprintf (f, "PASS THROUGH: ");
 	      fprintf (f, "%d\n", jump_func->value.formal_id);
@@ -353,7 +353,7 @@ compute_scalar_jump_functions (struct ipa_node_params *info,
 
       if (is_gimple_ip_invariant (arg))
 	{
-	  functions[num].type = IPA_CONST;
+	  functions[num].type = IPA_JF_CONST;
 	  functions[num].value.constant = arg;
 	}
       else if ((TREE_CODE (arg) == SSA_NAME) && SSA_NAME_IS_DEFAULT_DEF (arg))
@@ -362,7 +362,7 @@ compute_scalar_jump_functions (struct ipa_node_params *info,
 
 	  if (index >= 0)
 	    {
-	      functions[num].type = IPA_PASS_THROUGH;
+	      functions[num].type = IPA_JF_PASS_THROUGH;
 	      functions[num].value.formal_id = index;
 	    }
 	}
@@ -430,7 +430,7 @@ compute_pass_through_member_ptrs (struct ipa_node_params *info,
 	      gcc_assert (index >=0);
 	      if (!ipa_is_param_modified (info, index))
 		{
-		  functions[num].type = IPA_PASS_THROUGH;
+		  functions[num].type = IPA_JF_PASS_THROUGH;
 		  functions[num].value.formal_id = index;
 		}
 	      else
@@ -451,7 +451,7 @@ static void
 fill_member_ptr_cst_jump_function (struct ipa_jump_func *jfunc,
 				   tree pfn, tree delta)
 {
-  jfunc->type = IPA_CONST_MEMBER_PTR;
+  jfunc->type = IPA_JF_CONST_MEMBER_PTR;
   jfunc->value.member_cst.pfn = pfn;
   jfunc->value.member_cst.delta = delta;
 }
@@ -545,7 +545,7 @@ compute_cst_member_ptr_arguments (struct ipa_jump_func *functions,
     {
       arg = gimple_call_arg (call, num);
 
-      if (functions[num].type == IPA_UNKNOWN
+      if (functions[num].type == IPA_JF_UNKNOWN
 	  && type_like_member_ptr_p (TREE_TYPE (arg), &method_field,
 				     &delta_field))
 	determine_cst_member_ptr (call, arg, method_field, delta_field,
@@ -885,7 +885,7 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
     {
       struct ipa_jump_func *src, *dst = ipa_get_ith_jump_func (args, i);
 
-      if (dst->type != IPA_PASS_THROUGH)
+      if (dst->type != IPA_JF_PASS_THROUGH)
 	continue;
 
       /* We must check range due to calls with variable number of arguments:  */
@@ -910,7 +910,7 @@ print_edge_addition_message (FILE *f, struct ipa_param_call_note *nt,
 			     struct cgraph_node *node)
 {
   fprintf (f, "ipa-prop: Discovered an indirect call to a known target (");
-  if (jfunc->type == IPA_CONST_MEMBER_PTR)
+  if (jfunc->type == IPA_JF_CONST_MEMBER_PTR)
     {
       print_node_brief (f, "", jfunc->value.member_cst.pfn, 0);
       print_node_brief (f, ", ", jfunc->value.member_cst.delta, 0);
@@ -953,16 +953,17 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
 	}
 
       jfunc = ipa_get_ith_jump_func (top, nt->formal_id);
-      if (jfunc->type == IPA_PASS_THROUGH)
+      if (jfunc->type == IPA_JF_PASS_THROUGH)
 	nt->formal_id = jfunc->value.formal_id;
-      else if (jfunc->type == IPA_CONST || jfunc->type == IPA_CONST_MEMBER_PTR)
+      else if (jfunc->type == IPA_JF_CONST
+	       || jfunc->type == IPA_JF_CONST_MEMBER_PTR)
 	{
 	  struct cgraph_node *callee;
 	  struct cgraph_edge *new_indirect_edge;
 	  tree decl;
 
 	  nt->processed = true;
-	  if (jfunc->type == IPA_CONST_MEMBER_PTR)
+	  if (jfunc->type == IPA_JF_CONST_MEMBER_PTR)
 	    decl = jfunc->value.member_cst.pfn;
 	  else
 	    decl = jfunc->value.constant;
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index aca7bf8ef25373cdf7d34a5c03315a074d649827..5943a2af6f49a35b624c081b3ca71ff523066c5a 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -25,21 +25,24 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 
 /* The following definitions and interfaces are used by
-   interprocedural analyses.  */
+   interprocedural analyses or parameters.  */
+
+/* ipa-prop.c stuff (ipa-cp, indirect inlining):  */
 
 /* A jump function for a callsite represents the values passed as actual
    arguments of the callsite. There are three main types of values :
    Formal - the caller's formal parameter is passed as an actual argument.
    Constant - a constant is passed as an actual argument.
    Unknown - neither of the above.
-   Integer and real constants are represented as IPA_CONST.
-   Finally, IPA_CONST_MEMBER_PTR stands for C++ member pointers constants.  */
+   Integer and real constants are represented as IPA_JF_CONST.
+   Finally, IPA_JF_CONST_MEMBER_PTR stands for C++ member pointers
+   constants.  */
 enum jump_func_type
 {
-  IPA_UNKNOWN = 0,     /* newly allocated and zeroed jump functions default */
-  IPA_CONST,
-  IPA_CONST_MEMBER_PTR,
-  IPA_PASS_THROUGH
+  IPA_JF_UNKNOWN = 0,  /* newly allocated and zeroed jump functions default */
+  IPA_JF_CONST,
+  IPA_JF_CONST_MEMBER_PTR,
+  IPA_JF_PASS_THROUGH
 };
 
 /* All formal parameters in the program have a lattice associated with it
@@ -50,7 +53,7 @@ enum jump_func_type
    IPA_CONST_VALUE - simple scalar constant,
    Cval of formal f will have a constant value if all callsites to this
    function have the same constant value passed to f.
-   Integer and real constants are represented as IPA_CONST.  */
+   Integer and real constants are represented as IPA_CONST_VALUE.  */
 enum ipa_lattice_type
 {
   IPA_BOTTOM,
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index c56915f6546646086c1ae2b5575c7a93740e913d..40658760d38c1b08e16eedc10eb2bee41e7edb29 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -3244,6 +3244,7 @@ expand_omp_taskreg (struct omp_region *region)
   basic_block entry_bb, exit_bb, new_bb;
   struct function *child_cfun;
   tree child_fn, block, t, ws_args, *tp;
+  tree save_current;
   gimple_stmt_iterator gsi;
   gimple entry_stmt, stmt;
   edge e;
@@ -3429,6 +3430,8 @@ expand_omp_taskreg (struct omp_region *region)
       /* Fix the callgraph edges for child_cfun.  Those for cfun will be
 	 fixed in a following pass.  */
       push_cfun (child_cfun);
+      save_current = current_function_decl;
+      current_function_decl = child_fn;
       if (optimize)
 	optimize_omp_library_calls (entry_stmt);
       rebuild_cgraph_edges ();
@@ -3440,16 +3443,14 @@ expand_omp_taskreg (struct omp_region *region)
       if (flag_exceptions)
 	{
 	  basic_block bb;
-	  tree save_current = current_function_decl;
 	  bool changed = false;
 
-	  current_function_decl = child_fn;
 	  FOR_EACH_BB (bb)
 	    changed |= gimple_purge_dead_eh_edges (bb);
 	  if (changed)
 	    cleanup_tree_cfg ();
-	  current_function_decl = save_current;
 	}
+      current_function_decl = save_current;
       pop_cfun ();
     }
   
diff --git a/gcc/passes.c b/gcc/passes.c
index bf312f9171a2013641d1e93ce0d802a904f94863..4e8944ae1f77d92b20162b54be7363e77f431aab 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -551,6 +551,7 @@ init_optimization_passes (void)
 	  struct opt_pass **p = &pass_all_early_optimizations.pass.sub;
 	  NEXT_PASS (pass_rebuild_cgraph_edges);
 	  NEXT_PASS (pass_early_inline);
+	  NEXT_PASS (pass_remove_cgraph_callee_edges);
 	  NEXT_PASS (pass_rename_ssa_copies);
 	  NEXT_PASS (pass_ccp);
 	  NEXT_PASS (pass_forwprop);
@@ -587,6 +588,7 @@ init_optimization_passes (void)
   NEXT_PASS (pass_all_optimizations);
     {
       struct opt_pass **p = &pass_all_optimizations.pass.sub;
+      NEXT_PASS (pass_remove_cgraph_callee_edges);
       /* Initial scalar cleanups before alias computation.
 	 They ensure memory accesses are not indirect wherever possible.  */
       NEXT_PASS (pass_strip_predict_hints);
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 5241e64c9292e26f5960172621687ec8d4aa106e..082ac082bf382ebd7f81d0492fd1c14df68b44c7 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -801,6 +801,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
   tree size_tree = NULL_TREE;
   HOST_WIDE_INT bit_offset = 0;
   bool seen_variable_array_ref = false;
+  bool seen_union = false;
 
   gcc_assert (!SSA_VAR_P (exp));
 
@@ -844,6 +845,9 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
 	    tree field = TREE_OPERAND (exp, 1);
 	    tree this_offset = component_ref_field_offset (exp);
 
+	    if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == UNION_TYPE)
+	      seen_union = true;
+
 	    if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
 	      {
 		HOST_WIDE_INT hthis_offset = tree_low_cst (this_offset, 0);
@@ -934,12 +938,22 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
      where we do not know maxsize for variable index accesses to
      the array.  The simplest way to conservatively deal with this
      is to punt in the case that offset + maxsize reaches the
-     base type boundary.  */
+     base type boundary.
+
+     Unfortunately this is difficult to determine reliably when unions are
+     involved and so we are conservative in such cases.
+
+     FIXME: This approach may be too conservative, we probably want to at least
+     check that the union is the last field/element at its level or even
+     propagate the calculated offsets back up the access chain and check
+     there.  */
+
   if (seen_variable_array_ref
-      && maxsize != -1
-      && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
-      && bit_offset + maxsize
-	   == (signed)TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))
+      && (seen_union
+	  || (maxsize != -1
+	      && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+	      && bit_offset + maxsize
+	      == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
     maxsize = -1;
 
   /* ???  Due to negative offsets in ARRAY_REF we can end up with
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 37d9098034fb3afb7e36df54321ea2539e373660..609a0818ad77d8dae2e4023170658a8a576ed908 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3639,10 +3639,6 @@ optimize_inline_calls (tree fn)
   /* Renumber the lexical scoping (non-code) blocks consecutively.  */
   number_blocks (fn);
 
-  /* We are not going to maintain the cgraph edges up to date.
-     Kill it so it won't confuse us.  */
-  cgraph_node_remove_callees (id.dst_node);
-
   fold_cond_expr_cond ();
 
   /* It would be nice to check SSA/CFG/statement consistency here, but it is
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 96239c494d867f7eced5731a083453d4e81805eb..2db0f226510cff7e4883392f95f75ab33858b9c9 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -389,6 +389,7 @@ extern struct gimple_opt_pass pass_uncprop;
 extern struct gimple_opt_pass pass_return_slot;
 extern struct gimple_opt_pass pass_reassoc;
 extern struct gimple_opt_pass pass_rebuild_cgraph_edges;
+extern struct gimple_opt_pass pass_remove_cgraph_callee_edges;
 extern struct gimple_opt_pass pass_build_cgraph_edges;
 extern struct gimple_opt_pass pass_reset_cc_flags;
 extern struct gimple_opt_pass pass_local_pure_const;