--- /dev/null
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
+
+typedef struct rtx_def *rtx;
+enum rtx_code { MINUS };
+union rtunion_def {
+ rtx rt_rtx;
+};
+typedef union rtunion_def rtunion;
+struct rtx_def {
+ enum rtx_code code: 16;
+ union u {
+ rtunion fld[1];
+ }
+ u;
+};
+rtx simplify_binary_operation (enum rtx_code code, int mode,
+ rtx op0, rtx op1);
+struct simplify_plus_minus_op_data {
+ rtx op;
+ short neg;
+};
+void simplify_plus_minus (enum rtx_code code, int mode, rtx op0, rtx op1)
+{
+ struct simplify_plus_minus_op_data ops[8];
+ rtx tem = (rtx) 0;
+ int n_ops = 2, input_ops = 2;
+ int changed, canonicalized = 0;
+ int i, j;
+ __builtin_memset (ops, 0, sizeof (ops));
+ do
+ {
+ changed = 0;
+ for (i = 0; i < n_ops; i++)
+ {
+ rtx this_op = ops[i].op;
+ int this_neg = ops[i].neg;
+ enum rtx_code this_code = ((enum rtx_code) (this_op)->code);
+ switch (this_code)
+ {
+ case MINUS:
+ if (n_ops == 7)
+ return;
+ n_ops++;
+ input_ops++;
+ changed = 1;
+ canonicalized |= this_neg;
+ break;
+ }
+ }
+ }
+ while (changed);
+ do
+ {
+ j = n_ops - 1;
+ for (i = n_ops - 1; j >= 0; j--)
+ {
+ rtx lhs = ops[j].op, rhs = ops[i].op;
+ int lneg = ops[j].neg, rneg = ops[i].neg;
+ if (lhs != 0 && rhs != 0)
+ {
+ enum rtx_code ncode = MINUS;
+ if (((enum rtx_code) (lhs)->code) == MINUS)
+ tem = simplify_binary_operation (ncode, mode, lhs, rhs);
+ if (tem && ! (((enum rtx_code) (tem)->code) == MINUS
+ && ((((((tem)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx) == lhs
+ && ((((((tem)->u.fld[0]).rt_rtx))->u.fld[1]).rt_rtx) == rhs))
+ {
+ lneg &= rneg;
+ ops[i].op = tem;
+ ops[i].neg = lneg;
+ ops[j].op = (rtx) 0;
+ changed = 1;
+ canonicalized = 1;
+ }
+ }
+ }
+ for (i = 0, j = 0; j < n_ops; j++)
+ if (ops[j].op)
+ {
+ ops[i] = ops[j];
+ i++;
+ }
+ }
+ while (changed);
+}