+/**
+ * Optimize a - 0 and (a + x) - x (for modes with wrap-around).
+ *
+ * The second one looks strange, but this construct
+ * is used heavily in the LCC sources :-).
+ *
+ * Beware: The Mode of a Sub may be different than the mode of its
+ * predecessors, so we could not return a predecessors in all cases.
+ */
+static ir_node *equivalent_node_Sub(ir_node *n)
+{
+ ir_node *oldn = n;
+
+ ir_node *a = get_Sub_left(n);
+ ir_node *b = get_Sub_right(n);
+
+ /* Beware: modes might be different */
+ if (classify_tarval(value_of(b)) == TV_CLASSIFY_NULL) {
+ if (get_irn_mode(n) == get_irn_mode(a)) {
+ n = a;
+
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_NEUTRAL_0);
+ }
+ }
+ else if (get_irn_op(a) == op_Add) {
+ ir_mode *mode = get_irn_mode(n);
+
+ if (mode_wrap_around(mode)) {
+ ir_node *left = get_Add_left(a);
+ ir_node *right = get_Add_right(a);
+
+ if (left == b) {
+ if (get_irn_mode(n) == get_irn_mode(right)) {
+ n = right;
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_ADD_SUB);
+ }
+ }
+ else if (right == b) {
+ if (get_irn_mode(n) == get_irn_mode(left)) {
+ n = left;
+ DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_ADD_SUB);
+ }
+ }
+ }
+ }
+
+ return n;
+}
+
+