summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c31
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;
}