+ if (is_irn_constlike(node))
+ return;
+ /* insert or replace */
+ ir_nodehashmap_insert(map, node, trans);
+}
+
+/**
+ * Translates an expression above a Phi.
+ *
+ * @param node the node
+ * @param block the block the node is translated into
+ * @param pos the input number of the destination block
+ *
+ * @return a node representing the translated value
+ */
+static ir_node *phi_translate(ir_node *node, ir_node *block, int pos, ir_valueset_t *leaderset)
+{
+ int i;
+ int arity;
+ ir_node **in;
+ ir_node *pred_block = get_Block_cfgpred_block(block, pos);
+ ir_node *nn;
+ unsigned needed;
+
+ if (is_Phi(node)) {
+ if (get_nodes_block(node) == block)
+ return get_Phi_pred(node, pos);
+ /* this phi does not need translation */
+ return node;
+ }
+ arity = get_irn_arity(node);
+
+ needed = 0;
+ in = ALLOCANZ(ir_node *, arity);
+
+ /* A value has several representatives. The anti leader is chosen to be
+ the main representative. If we access a node as representative of a
+ value we always use the anti leader. The anti leader can be found by
+ antic_in(identify(node)). */
+ for (i = 0; i < arity; ++i) {
+ ir_node *pred = get_irn_n(node, i);
+ ir_node *value = identify(pred);
+ /* get leader for pred to lookup its translated value */
+ ir_node *leader = ir_valueset_lookup(leaderset, value);
+ ir_node *pred_trans;
+ ir_node *new_pred;
+
+ if (! leader)
+ leader = pred;
+
+ /* we cannot find this value in antic_in, because the value
+ has (possibly) changed! */
+ pred_trans = get_translated(pred_block, leader);
+
+
+#if DIVMODS
+ if (is_Div(node)) {
+ ir_node *mem = get_Div_mem(node);
+
+ mem = skip_Pin(mem);
+
+ if (! is_Phi(mem))
+ pred_trans = get_Div_mem(node);
+ }
+#endif
+
+ DB((dbg, LEVEL_3, "trans %+F of %+F is %+F\n", leader, pred_block, pred_trans));
+ if (pred_trans == NULL) {
+ new_pred = pred;
+ } else {
+ new_pred = pred_trans;
+
+ /* loads: Predecessor is a memory phi, which translated yields a proj or
+ another phi. In case of projection and a load predecessor,
+ skip them and use the loads memory. */
+ if (is_Proj(pred_trans) && get_irn_mode(pred_trans) == mode_M) {
+#if LOADS || DIVMODS
+ ir_node *loadstore = get_Proj_pred(pred_trans);
+ /* If we do not translate this node, we will get its value wrong. */
+ needed |= 1;
+
+ if (is_Load(loadstore)) {
+ /* Put new load under the adjacent loads memory edge
+ such that GVN may compare them. */
+ new_pred = get_Load_mem(loadstore);
+ } else if (is_Store(loadstore)) {
+ new_pred = get_Store_mem(loadstore);
+ }
+#endif
+ } else {
+ /* predecessor value changed, so translation is needed */
+ if (identify(new_pred) != identify(pred))
+ needed |= 1;
+ }
+ }
+
+ DB((dbg, LEVEL_4, "in %+F\n", new_pred));
+ in[i] = new_pred;
+ }
+
+ if (! needed)
+ return node;
+
+ DB((dbg, LEVEL_3, "Translate\n"));
+
+ if (is_Proj(node))
+ pred_block = get_nodes_block(in[0]);
+
+ /* copy node to represent the new value.
+ We do not translate nodes that do not need translation,
+ so we use the newly created nodes as value representatives only.
+ Their block is not important, because we create new ones during
+ the insert node phase. */
+ nn = new_ir_node(
+ get_irn_dbg_info(node),
+ environ->graph,
+ pred_block,
+ get_irn_op(node),
+ get_irn_mode(node),
+ arity,
+ in);
+ /* We need the attribute copy here, because the Hash value of a
+ node might depend on it. */
+ copy_node_attr(environ->graph, node, nn);
+ /* Optimizing nn here is tempting but might be against the GVN-PRE algorithm
+ because it already uses availability. */
+
+ DB((dbg, LEVEL_3, "New node %+F in %+F origin %+F\n", nn, get_Block_cfgpred_block(block, pos), node));
+ return nn;
+}