aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/region-model-manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/region-model-manager.cc')
-rw-r--r--gcc/analyzer/region-model-manager.cc32
1 files changed, 25 insertions, 7 deletions
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index 3b95e43..1453acf 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -230,10 +230,11 @@ region_model_manager::get_or_create_constant_svalue (tree cst_expr)
for VAL of type TYPE, creating it if necessary. */
const svalue *
-region_model_manager::get_or_create_int_cst (tree type, poly_int64 val)
+region_model_manager::get_or_create_int_cst (tree type,
+ const poly_wide_int_ref &cst)
{
gcc_assert (type);
- tree tree_cst = build_int_cst (type, val);
+ tree tree_cst = wide_int_to_tree (type, cst);
return get_or_create_constant_svalue (tree_cst);
}
@@ -612,7 +613,7 @@ region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
return get_or_create_constant_svalue (result);
}
- if (FLOAT_TYPE_P (type)
+ if ((type && FLOAT_TYPE_P (type))
|| (arg0->get_type () && FLOAT_TYPE_P (arg0->get_type ()))
|| (arg1->get_type () && FLOAT_TYPE_P (arg1->get_type ())))
return NULL;
@@ -634,6 +635,11 @@ region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
/* (0 - VAL) -> -VAL. */
if (cst0 && zerop (cst0))
return get_or_create_unaryop (type, NEGATE_EXPR, arg1);
+ /* (X + Y) - X -> Y. */
+ if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
+ if (binop->get_op () == PLUS_EXPR)
+ if (binop->get_arg0 () == arg1)
+ return get_or_create_cast (type, binop->get_arg1 ());
break;
case MULT_EXPR:
/* (VAL * 0). */
@@ -726,10 +732,7 @@ region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
if (cst1 && associative_tree_code (op))
if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
if (binop->get_op () == op
- && binop->get_arg1 ()->maybe_get_constant ()
- && type == binop->get_type ()
- && type == binop->get_arg0 ()->get_type ()
- && type == binop->get_arg1 ()->get_type ())
+ && binop->get_arg1 ()->maybe_get_constant ())
return get_or_create_binop
(type, op, binop->get_arg0 (),
get_or_create_binop (type, op,
@@ -748,6 +751,21 @@ region_model_manager::maybe_fold_binop (tree type, enum tree_code op,
get_or_create_binop (size_type_node, op,
binop->get_arg1 (), arg1));
+ /* Distribute multiplication by a constant through addition/subtraction:
+ (X + Y) * CST => (X * CST) + (Y * CST). */
+ if (cst1 && op == MULT_EXPR)
+ if (const binop_svalue *binop = arg0->dyn_cast_binop_svalue ())
+ if (binop->get_op () == PLUS_EXPR
+ || binop->get_op () == MINUS_EXPR)
+ {
+ return get_or_create_binop
+ (type, binop->get_op (),
+ get_or_create_binop (type, op,
+ binop->get_arg0 (), arg1),
+ get_or_create_binop (type, op,
+ binop->get_arg1 (), arg1));
+ }
+
/* etc. */
return NULL;