| /* { 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); |
| } |