diff options
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 134 |
1 files changed, 88 insertions, 46 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 36dd9a17335..fb222f7ae6b 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -773,7 +773,17 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode, case FIX: real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); break; - + case NOT: + { + long tmp[4]; + int i; + + real_to_target (tmp, &d, GET_MODE (trueop)); + for (i = 0; i < 4; i++) + tmp[i] = ~tmp[i]; + real_from_target (&d, tmp, mode); + break; + } default: abort (); } @@ -1184,6 +1194,7 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, } if (VECTOR_MODE_P (mode) + && code != VEC_CONCAT && GET_CODE (trueop0) == CONST_VECTOR && GET_CODE (trueop1) == CONST_VECTOR) { @@ -1219,60 +1230,91 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, && GET_CODE (trueop1) == CONST_DOUBLE && mode == GET_MODE (op0) && mode == GET_MODE (op1)) { - REAL_VALUE_TYPE f0, f1, value; - - REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0); - REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1); - f0 = real_value_truncate (mode, f0); - f1 = real_value_truncate (mode, f1); + if (code == AND + || code == IOR + || code == XOR) + { + long tmp0[4]; + long tmp1[4]; + REAL_VALUE_TYPE r; + int i; + + real_to_target (tmp0, CONST_DOUBLE_REAL_VALUE (op0), + GET_MODE (op0)); + real_to_target (tmp1, CONST_DOUBLE_REAL_VALUE (op1), + GET_MODE (op1)); + for (i = 0; i < 4; i++) + { + if (code == AND) + tmp0[i] &= tmp1[i]; + else if (code == IOR) + tmp0[i] |= tmp1[i]; + else if (code == XOR) + tmp0[i] ^= tmp1[i]; + else + abort (); + } + real_from_target (&r, tmp0, mode); + return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); + } + else + { + REAL_VALUE_TYPE f0, f1, value; - if (HONOR_SNANS (mode) - && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1))) - return 0; + REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0); + REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1); + f0 = real_value_truncate (mode, f0); + f1 = real_value_truncate (mode, f1); - if (code == DIV - && REAL_VALUES_EQUAL (f1, dconst0) - && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) - return 0; + if (HONOR_SNANS (mode) + && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1))) + return 0; - if (MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) - && flag_trapping_math - && REAL_VALUE_ISINF (f0) && REAL_VALUE_ISINF (f1)) - { - int s0 = REAL_VALUE_NEGATIVE (f0); - int s1 = REAL_VALUE_NEGATIVE (f1); + if (code == DIV + && REAL_VALUES_EQUAL (f1, dconst0) + && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) + return 0; - switch (code) + if (MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) + && flag_trapping_math + && REAL_VALUE_ISINF (f0) && REAL_VALUE_ISINF (f1)) { - case PLUS: - /* Inf + -Inf = NaN plus exception. */ - if (s0 != s1) - return 0; - break; - case MINUS: - /* Inf - Inf = NaN plus exception. */ - if (s0 == s1) - return 0; - break; - case DIV: - /* Inf / Inf = NaN plus exception. */ - return 0; - default: - break; + int s0 = REAL_VALUE_NEGATIVE (f0); + int s1 = REAL_VALUE_NEGATIVE (f1); + + switch (code) + { + case PLUS: + /* Inf + -Inf = NaN plus exception. */ + if (s0 != s1) + return 0; + break; + case MINUS: + /* Inf - Inf = NaN plus exception. */ + if (s0 == s1) + return 0; + break; + case DIV: + /* Inf / Inf = NaN plus exception. */ + return 0; + default: + break; + } } - } - if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) - && flag_trapping_math - && ((REAL_VALUE_ISINF (f0) && REAL_VALUES_EQUAL (f1, dconst0)) - || (REAL_VALUE_ISINF (f1) && REAL_VALUES_EQUAL (f0, dconst0)))) - /* Inf * 0 = NaN plus exception. */ - return 0; + if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode) + && flag_trapping_math + && ((REAL_VALUE_ISINF (f0) && REAL_VALUES_EQUAL (f1, dconst0)) + || (REAL_VALUE_ISINF (f1) + && REAL_VALUES_EQUAL (f0, dconst0)))) + /* Inf * 0 = NaN plus exception. */ + return 0; - REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1); + REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1); - value = real_value_truncate (mode, value); - return CONST_DOUBLE_FROM_REAL_VALUE (value, mode); + value = real_value_truncate (mode, value); + return CONST_DOUBLE_FROM_REAL_VALUE (value, mode); + } } /* We can fold some multi-word operations. */ |