summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authormanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>2008-10-29 17:16:46 +0000
committermanu <manu@138bc75d-0d04-0410-961f-82ee72b054a4>2008-10-29 17:16:46 +0000
commit5485b95993fb050b72cda916567017a2e3698373 (patch)
tree42ccc636ef21cba0db86051f05076ac6b24aa628 /gcc/fold-const.c
parent02c52e944f67987d3e2a506e9e3e9c60282db7ae (diff)
downloadgcc-5485b95993fb050b72cda916567017a2e3698373.tar.gz
2008-10-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 11492 * c-common.c (min_precision): Move to... * tree.c (tree_int_cst_min_precision): ... to here. Renamed. * tree.h (tree_int_cst_min_precision): Declare. * c-common.h (min_precision): Delete declaration. * fold-const.c (tree_binary_nonnegative_warnv_p): Handle multiplication of non-negative integer constants. * c-decl.c (check_bitfield_type_and_width): Rename min_precision to tree_int_cst_min_precision. (finish_enum): Likewise. cp/ * class.c (check_bitfield_decl): Rename min_precision to tree_int_cst_min_precision. * decl.c (finish_enum): Likewise. testsuite/ * gcc.dg/pr11492.c: New. * g++.dg/warn/pr11492.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141434 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7a215d27cb4..1a96c3f77fc 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -14016,15 +14016,38 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
/* zero_extend(x) * zero_extend(y) is non-negative if x and y are
both unsigned and their total bits is shorter than the result. */
if (TREE_CODE (type) == INTEGER_TYPE
- && TREE_CODE (op0) == NOP_EXPR
- && TREE_CODE (op1) == NOP_EXPR)
+ && (TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == INTEGER_CST)
+ && (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == INTEGER_CST))
{
- tree inner1 = TREE_TYPE (TREE_OPERAND (op0, 0));
- tree inner2 = TREE_TYPE (TREE_OPERAND (op1, 0));
- if (TREE_CODE (inner1) == INTEGER_TYPE && TYPE_UNSIGNED (inner1)
- && TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2))
- return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2)
- < TYPE_PRECISION (type);
+ tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
+ ? TREE_TYPE (TREE_OPERAND (op0, 0))
+ : TREE_TYPE (op0);
+ tree inner1 = (TREE_CODE (op1) == NOP_EXPR)
+ ? TREE_TYPE (TREE_OPERAND (op1, 0))
+ : TREE_TYPE (op1);
+
+ bool unsigned0 = TYPE_UNSIGNED (inner0);
+ bool unsigned1 = TYPE_UNSIGNED (inner1);
+
+ if (TREE_CODE (op0) == INTEGER_CST)
+ unsigned0 = unsigned0 || tree_int_cst_sgn (op0) >= 0;
+
+ if (TREE_CODE (op1) == INTEGER_CST)
+ unsigned1 = unsigned1 || tree_int_cst_sgn (op1) >= 0;
+
+ if (TREE_CODE (inner0) == INTEGER_TYPE && unsigned0
+ && TREE_CODE (inner1) == INTEGER_TYPE && unsigned1)
+ {
+ unsigned int precision0 = (TREE_CODE (op0) == INTEGER_CST)
+ ? tree_int_cst_min_precision (op0, /*unsignedp=*/true)
+ : TYPE_PRECISION (inner0);
+
+ unsigned int precision1 = (TREE_CODE (op1) == INTEGER_CST)
+ ? tree_int_cst_min_precision (op1, /*unsignedp=*/true)
+ : TYPE_PRECISION (inner1);
+
+ return precision0 + precision1 < TYPE_PRECISION (type);
+ }
}
return false;