+/* Re-create a reference tree from the reference ops OPS.
+ Returns NULL_TREE if the ops were not handled.
+ This routine needs to be kept in sync with copy_reference_ops_from_ref. */
+
+static tree
+get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops)
+{
+ vn_reference_op_t op;
+ unsigned i;
+ tree ref, *op0_p = &ref;
+
+ for (i = 0; VEC_iterate (vn_reference_op_s, ops, i, op); ++i)
+ {
+ switch (op->opcode)
+ {
+ case CALL_EXPR:
+ return NULL_TREE;
+
+ case ALIGN_INDIRECT_REF:
+ case INDIRECT_REF:
+ *op0_p = build1 (op->opcode, op->type, NULL_TREE);
+ op0_p = &TREE_OPERAND (*op0_p, 0);
+ break;
+
+ case MISALIGNED_INDIRECT_REF:
+ *op0_p = build2 (MISALIGNED_INDIRECT_REF, op->type,
+ NULL_TREE, op->op0);
+ op0_p = &TREE_OPERAND (*op0_p, 0);
+ break;
+
+ case BIT_FIELD_REF:
+ *op0_p = build3 (BIT_FIELD_REF, op->type, NULL_TREE,
+ op->op0, op->op1);
+ op0_p = &TREE_OPERAND (*op0_p, 0);
+ break;
+
+ case COMPONENT_REF:
+ *op0_p = build3 (COMPONENT_REF, TREE_TYPE (op->op0), NULL_TREE,
+ op->op0, op->op1);
+ op0_p = &TREE_OPERAND (*op0_p, 0);
+ break;
+
+ case ARRAY_RANGE_REF:
+ case ARRAY_REF:
+ *op0_p = build4 (op->opcode, op->type, NULL_TREE,
+ op->op0, op->op1, op->op2);
+ op0_p = &TREE_OPERAND (*op0_p, 0);
+ break;
+
+ case STRING_CST:
+ case INTEGER_CST:
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ case REAL_CST:
+ case CONSTRUCTOR:
+ case VAR_DECL:
+ case PARM_DECL:
+ case CONST_DECL:
+ case RESULT_DECL:
+ case SSA_NAME:
+ *op0_p = op->op0;
+ break;
+
+ case ADDR_EXPR:
+ if (op->op0 != NULL_TREE)
+ {
+ gcc_assert (is_gimple_min_invariant (op->op0));
+ *op0_p = op->op0;
+ break;
+ }
+ /* Fallthrough. */
+ case IMAGPART_EXPR:
+ case REALPART_EXPR:
+ case VIEW_CONVERT_EXPR:
+ *op0_p = build1 (op->opcode, op->type, NULL_TREE);
+ op0_p = &TREE_OPERAND (*op0_p, 0);
+ break;
+
+ default:
+ return NULL_TREE;
+ }
+ }
+
+ return ref;
+}
+
+/* Copy the operations present in load/store/call REF into RESULT, a vector of
+ vn_reference_op_s's. */
+
+void
+copy_reference_ops_from_call (gimple call,
+ VEC(vn_reference_op_s, heap) **result)
+{
+ vn_reference_op_s temp;
+ unsigned i;
+
+ /* Copy the type, opcode, function being called and static chain. */
+ memset (&temp, 0, sizeof (temp));
+ temp.type = gimple_call_return_type (call);
+ temp.opcode = CALL_EXPR;
+ temp.op0 = gimple_call_fn (call);
+ temp.op1 = gimple_call_chain (call);
+ VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+
+ /* Copy the call arguments. As they can be references as well,
+ just chain them together. */
+ for (i = 0; i < gimple_call_num_args (call); ++i)
+ {
+ tree callarg = gimple_call_arg (call, i);
+ copy_reference_ops_from_ref (callarg, result);
+ }
+}
+