+/**
+ * Check whether the node has only one user. Explicitly ignore the anchor.
+ */
+static int has_only_one_user(ir_node *node)
+{
+ int n = get_irn_n_edges(node);
+ const ir_edge_t *edge;
+
+ if (n <= 1)
+ return 1;
+
+ if (n > 2)
+ return 0;
+
+ foreach_out_edge(node, edge) {
+ ir_node *src = get_edge_src_irn(edge);
+ if (is_Anchor(src))
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Tries to optimize a beIncSP node with its previous IncSP node.
+ * Must be run from a be_peephole_opt() context.
+ */
+ir_node *be_peephole_IncSP_IncSP(ir_node *node)
+{
+ int pred_offs;
+ int curr_offs;
+ int offs;
+ ir_node *pred = be_get_IncSP_pred(node);
+
+ if (!be_is_IncSP(pred))
+ return node;
+
+ if (!has_only_one_user(pred))
+ return node;
+
+ pred_offs = be_get_IncSP_offset(pred);
+ curr_offs = be_get_IncSP_offset(node);
+
+ if (pred_offs == BE_STACK_FRAME_SIZE_EXPAND) {
+ if (curr_offs != BE_STACK_FRAME_SIZE_SHRINK) {
+ return node;
+ }
+ offs = 0;
+ } else if (pred_offs == BE_STACK_FRAME_SIZE_SHRINK) {
+ if (curr_offs != BE_STACK_FRAME_SIZE_EXPAND) {
+ return node;
+ }
+ offs = 0;
+ } else if (curr_offs == BE_STACK_FRAME_SIZE_EXPAND ||
+ curr_offs == BE_STACK_FRAME_SIZE_SHRINK) {
+ return node;
+ } else {
+ offs = curr_offs + pred_offs;
+ }
+
+ /* add node offset to pred and remove our IncSP */
+ be_set_IncSP_offset(pred, offs);
+
+ be_peephole_exchange(node, pred);
+ return pred;
+}