aboutsummaryrefslogtreecommitdiff
path: root/gcc/convert.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2010-02-10 11:54:14 +0000
committerRichard Guenther <rguenther@suse.de>2010-02-10 11:54:14 +0000
commit8eb8358165c45e3c8d8493aafa2c61ced3afb52c (patch)
tree6113ddc6064eef820caaf65171d7e8681efc3368 /gcc/convert.c
parentf0ebcc9be7bece602cd1ef531017f01d4aab2be5 (diff)
2010-02-10 Richard Guenther <rguenther@suse.de>
PR c/43007 * tree.c (get_unwidened): Handle constants. * convert.c (convert_to_integer): Handle TRUNC_DIV_EXPR. * gcc.c-torture/execute/20100209-1.c: New testcase. * gcc.dg/fold-div-3.c: Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@156653 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/convert.c')
-rw-r--r--gcc/convert.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/gcc/convert.c b/gcc/convert.c
index 4fe95ced915..39fbd4d4fa5 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -673,6 +673,31 @@ convert_to_integer (tree type, tree expr)
}
break;
+ case TRUNC_DIV_EXPR:
+ {
+ tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);
+ tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);
+
+ /* Don't distribute unless the output precision is at least as big
+ as the actual inputs and it has the same signedness. */
+ if (outprec >= TYPE_PRECISION (TREE_TYPE (arg0))
+ && outprec >= TYPE_PRECISION (TREE_TYPE (arg1))
+ /* If signedness of arg0 and arg1 don't match,
+ we can't necessarily find a type to compare them in. */
+ && (TYPE_UNSIGNED (TREE_TYPE (arg0))
+ == TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ /* Do not change the sign of the division. */
+ && (TYPE_UNSIGNED (TREE_TYPE (expr))
+ == TYPE_UNSIGNED (TREE_TYPE (arg0)))
+ /* Either require unsigned division or a division by
+ a constant that is not -1. */
+ && (TYPE_UNSIGNED (TREE_TYPE (arg0))
+ || (TREE_CODE (arg1) == INTEGER_CST
+ && !integer_all_onesp (arg1))))
+ goto trunc1;
+ break;
+ }
+
case MAX_EXPR:
case MIN_EXPR:
case MULT_EXPR: