diff options
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 58b6c70df4c..5e18d6862ac 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -920,6 +920,18 @@ negate_expr_p (tree t) return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))); break; + case RSHIFT_EXPR: + /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */ + if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) + { + tree op1 = TREE_OPERAND (t, 1); + if (TREE_INT_CST_HIGH (op1) == 0 + && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1) + == TREE_INT_CST_LOW (op1)) + return true; + } + break; + default: break; } @@ -1065,6 +1077,25 @@ negate_expr (tree t) } break; + case RSHIFT_EXPR: + /* Optimize -((int)x >> 31) into (unsigned)x >> 31. */ + if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) + { + tree op1 = TREE_OPERAND (t, 1); + if (TREE_INT_CST_HIGH (op1) == 0 + && (unsigned HOST_WIDE_INT) (TYPE_PRECISION (type) - 1) + == TREE_INT_CST_LOW (op1)) + { + tree ntype = TREE_UNSIGNED (type) + ? (*lang_hooks.types.signed_type) (type) + : (*lang_hooks.types.unsigned_type) (type); + tree temp = fold_convert (ntype, TREE_OPERAND (t, 0)); + temp = fold (build2 (RSHIFT_EXPR, ntype, temp, op1)); + return fold_convert (type, temp); + } + } + break; + default: break; } |