+ case tcc_vl_exp:
+ {
+ if (TREE_CODE (expr) != CALL_EXPR)
+ return NULL;
+ else
+ {
+ tree oldfn = CALL_EXPR_FN (expr);
+ tree oldsc = CALL_EXPR_STATIC_CHAIN (expr);
+ tree newfn, newsc = NULL;
+ tree newexpr = NULL_TREE;
+ tree vh = get_value_handle (expr);
+ bool invariantarg = false;
+ int i, nargs;
+ VEC (tree, gc) *vuses = VALUE_HANDLE_VUSES (vh);
+ VEC (tree, gc) *tvuses;
+
+ newfn = phi_translate (find_leader_in_sets (oldfn, set1, set2),
+ set1, set2, pred, phiblock);
+ if (newfn == NULL)
+ return NULL;
+ if (newfn != oldfn)
+ {
+ newexpr = temp_copy_call_expr (expr);
+ CALL_EXPR_FN (newexpr) = get_value_handle (newfn);
+ }
+ if (oldsc)
+ {
+ newsc = phi_translate (find_leader_in_sets (oldsc, set1, set2),
+ set1, set2, pred, phiblock);
+ if (newsc == NULL)
+ return NULL;
+ if (newsc != oldsc)
+ {
+ if (!newexpr)
+ newexpr = temp_copy_call_expr (expr);
+ CALL_EXPR_STATIC_CHAIN (newexpr) = get_value_handle (newsc);
+ }
+ }
+
+ /* phi translate the argument list piece by piece. */
+ nargs = call_expr_nargs (expr);
+ for (i = 0; i < nargs; i++)
+ {
+ tree oldval = CALL_EXPR_ARG (expr, i);
+ tree newval;
+ if (oldval)
+ {
+ /* This may seem like a weird place for this
+ check, but it's actually the easiest place to
+ do it. We can't do it lower on in the
+ recursion because it's valid for pieces of a
+ component ref to be of AGGREGATE_TYPE, as long
+ as the outermost one is not.
+ To avoid *that* case, we have a check for
+ AGGREGATE_TYPE_P in insert_aux. However, that
+ check will *not* catch this case because here
+ it occurs in the argument list. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (oldval)))
+ return NULL;
+ oldval = find_leader_in_sets (oldval, set1, set2);
+ newval = phi_translate (oldval, set1, set2, pred,
+ phiblock);
+ if (newval == NULL)
+ return NULL;
+ if (newval != oldval)
+ {
+ invariantarg |= is_gimple_min_invariant (newval);
+ if (!newexpr)
+ newexpr = temp_copy_call_expr (expr);
+ CALL_EXPR_ARG (newexpr, i) = get_value_handle (newval);
+ }
+ }
+ }
+
+ /* In case of new invariant args we might try to fold the call
+ again. */
+ if (invariantarg && !newsc)
+ {
+ tree tmp1 = build_call_array (TREE_TYPE (expr),
+ newfn, call_expr_nargs (newexpr),
+ CALL_EXPR_ARGP (newexpr));
+ tree tmp2 = fold (tmp1);
+ if (tmp2 != tmp1)
+ {
+ STRIP_TYPE_NOPS (tmp2);
+ if (is_gimple_min_invariant (tmp2))
+ return tmp2;
+ }
+ }
+
+ tvuses = translate_vuses_through_block (vuses, phiblock, pred);
+ if (vuses != tvuses && ! newexpr)
+ newexpr = temp_copy_call_expr (expr);
+
+ if (newexpr)
+ {
+ newexpr->base.ann = NULL;
+ vn_lookup_or_add_with_vuses (newexpr, tvuses);
+ expr = newexpr;
+ }
+ phi_trans_add (oldexpr, expr, pred, tvuses);
+ }
+ }
+ return expr;
+
+ case tcc_declaration:
+ {
+ VEC (tree, gc) * oldvuses = NULL;
+ VEC (tree, gc) * newvuses = NULL;
+
+ oldvuses = VALUE_HANDLE_VUSES (get_value_handle (expr));
+ if (oldvuses)
+ newvuses = translate_vuses_through_block (oldvuses, phiblock,
+ pred);
+
+ if (oldvuses != newvuses)
+ vn_lookup_or_add_with_vuses (expr, newvuses);
+
+ phi_trans_add (oldexpr, expr, pred, newvuses);
+ }
+ return expr;
+
+ case tcc_reference:
+ {
+ tree oldop0 = TREE_OPERAND (expr, 0);
+ tree oldop1 = NULL;
+ tree newop0;
+ tree newop1 = NULL;
+ tree oldop2 = NULL;
+ tree newop2 = NULL;
+ tree oldop3 = NULL;
+ tree newop3 = NULL;
+ tree newexpr;
+ VEC (tree, gc) * oldvuses = NULL;
+ VEC (tree, gc) * newvuses = NULL;
+
+ if (TREE_CODE (expr) != INDIRECT_REF
+ && TREE_CODE (expr) != COMPONENT_REF
+ && TREE_CODE (expr) != ARRAY_REF)
+ return NULL;
+
+ oldop0 = find_leader_in_sets (oldop0, set1, set2);
+ newop0 = phi_translate (oldop0, set1, set2, pred, phiblock);
+ if (newop0 == NULL)
+ return NULL;
+
+ if (TREE_CODE (expr) == ARRAY_REF)
+ {
+ oldop1 = TREE_OPERAND (expr, 1);
+ oldop1 = find_leader_in_sets (oldop1, set1, set2);
+ newop1 = phi_translate (oldop1, set1, set2, pred, phiblock);
+
+ if (newop1 == NULL)
+ return NULL;
+
+ oldop2 = TREE_OPERAND (expr, 2);
+ if (oldop2)
+ {
+ oldop2 = find_leader_in_sets (oldop2, set1, set2);
+ newop2 = phi_translate (oldop2, set1, set2, pred, phiblock);
+
+ if (newop2 == NULL)
+ return NULL;
+ }
+ oldop3 = TREE_OPERAND (expr, 3);
+ if (oldop3)
+ {
+ oldop3 = find_leader_in_sets (oldop3, set1, set2);
+ newop3 = phi_translate (oldop3, set1, set2, pred, phiblock);
+
+ if (newop3 == NULL)
+ return NULL;
+ }
+ }
+
+ oldvuses = VALUE_HANDLE_VUSES (get_value_handle (expr));
+ if (oldvuses)
+ newvuses = translate_vuses_through_block (oldvuses, phiblock,
+ pred);
+
+ if (newop0 != oldop0 || newvuses != oldvuses
+ || newop1 != oldop1
+ || newop2 != oldop2
+ || newop3 != oldop3)
+ {
+ tree t;
+
+ newexpr = (tree) pool_alloc (reference_node_pool);
+ memcpy (newexpr, expr, tree_size (expr));
+ TREE_OPERAND (newexpr, 0) = get_value_handle (newop0);
+ if (TREE_CODE (expr) == ARRAY_REF)
+ {
+ TREE_OPERAND (newexpr, 1) = get_value_handle (newop1);
+ if (newop2)
+ TREE_OPERAND (newexpr, 2) = get_value_handle (newop2);
+ if (newop3)
+ TREE_OPERAND (newexpr, 3) = get_value_handle (newop3);
+ }
+
+ t = fully_constant_expression (newexpr);
+
+ if (t != newexpr)
+ {
+ pool_free (reference_node_pool, newexpr);
+ newexpr = t;
+ }
+ else
+ {
+ newexpr->base.ann = NULL;
+ vn_lookup_or_add_with_vuses (newexpr, newvuses);
+ }
+ expr = newexpr;
+ }
+ phi_trans_add (oldexpr, expr, pred, newvuses);
+ }
+ return expr;
+ break;
+