aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 8ab6d76..4de7c4d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -9299,6 +9299,68 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
return true;
}
+/* Simplify an internal fn call using ranges if possible. */
+
+static bool
+simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
+{
+ enum tree_code subcode;
+ switch (gimple_call_internal_fn (stmt))
+ {
+ case IFN_UBSAN_CHECK_ADD:
+ subcode = PLUS_EXPR;
+ break;
+ case IFN_UBSAN_CHECK_SUB:
+ subcode = MINUS_EXPR;
+ break;
+ case IFN_UBSAN_CHECK_MUL:
+ subcode = MULT_EXPR;
+ break;
+ default:
+ return false;
+ }
+
+ value_range_t vr0 = VR_INITIALIZER;
+ value_range_t vr1 = VR_INITIALIZER;
+ tree op0 = gimple_call_arg (stmt, 0);
+ tree op1 = gimple_call_arg (stmt, 1);
+
+ if (TREE_CODE (op0) == SSA_NAME)
+ vr0 = *get_value_range (op0);
+ else if (TREE_CODE (op0) == INTEGER_CST)
+ set_value_range_to_value (&vr0, op0, NULL);
+ else
+ return false;
+
+ if (TREE_CODE (op1) == SSA_NAME)
+ vr1 = *get_value_range (op1);
+ else if (TREE_CODE (op1) == INTEGER_CST)
+ set_value_range_to_value (&vr1, op1, NULL);
+ else
+ return false;
+
+ if (!range_int_cst_p (&vr0) || !range_int_cst_p (&vr1))
+ return false;
+
+ tree r1 = int_const_binop (subcode, vr0.min, vr1.min);
+ tree r2 = int_const_binop (subcode, vr0.max, vr1.max);
+ if (r1 == NULL_TREE || TREE_OVERFLOW (r1)
+ || r2 == NULL_TREE || TREE_OVERFLOW (r2))
+ return false;
+ if (subcode == MULT_EXPR)
+ {
+ tree r3 = int_const_binop (subcode, vr0.min, vr1.max);
+ tree r4 = int_const_binop (subcode, vr0.max, vr1.min);
+ if (r3 == NULL_TREE || TREE_OVERFLOW (r3)
+ || r4 == NULL_TREE || TREE_OVERFLOW (r4))
+ return false;
+ }
+ gimple g = gimple_build_assign_with_ops (subcode, gimple_call_lhs (stmt),
+ op0, op1);
+ gsi_replace (gsi, g, false);
+ return true;
+}
+
/* Simplify STMT using ranges if possible. */
static bool
@@ -9367,6 +9429,9 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
return simplify_cond_using_ranges (stmt);
else if (gimple_code (stmt) == GIMPLE_SWITCH)
return simplify_switch_using_ranges (stmt);
+ else if (is_gimple_call (stmt)
+ && gimple_call_internal_p (stmt))
+ return simplify_internal_call_using_ranges (gsi, stmt);
return false;
}