aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorBen Cheng <bccheng@google.com>2014-04-22 13:33:12 -0700
committerBen Cheng <bccheng@google.com>2014-04-22 13:33:12 -0700
commite3cc64dec20832769406aa38cde83c7dd4194bf4 (patch)
treeef8e39be37cfe0cb69d850043b7924389ff17164 /gcc-4.9/gcc/gimple-fold.c
parentf33c7b3122b1d7950efa88067c9a156229ba647b (diff)
downloadtoolchain_gcc-e3cc64dec20832769406aa38cde83c7dd4194bf4.tar.gz
toolchain_gcc-e3cc64dec20832769406aa38cde83c7dd4194bf4.tar.bz2
toolchain_gcc-e3cc64dec20832769406aa38cde83c7dd4194bf4.zip
[4.9] GCC 4.9.0 official release refresh
Change-Id: Ic99a7da8b44b789a48aeec93b33e93944d6e6767
Diffstat (limited to 'gcc-4.9/gcc/gimple-fold.c')
-rw-r--r--gcc-4.9/gcc/gimple-fold.c84
1 files changed, 72 insertions, 12 deletions
diff --git a/gcc-4.9/gcc/gimple-fold.c b/gcc-4.9/gcc/gimple-fold.c
index 267c1fdad..6402cce2f 100644
--- a/gcc-4.9/gcc/gimple-fold.c
+++ b/gcc-4.9/gcc/gimple-fold.c
@@ -1186,13 +1186,56 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
else if (gimple_call_builtin_p (stmt, BUILT_IN_MD))
changed |= targetm.gimple_fold_builtin (gsi);
}
- else if (gimple_call_internal_p (stmt)
- && gimple_call_internal_fn (stmt) == IFN_BUILTIN_EXPECT)
+ else if (gimple_call_internal_p (stmt))
{
- tree result = fold_builtin_expect (gimple_location (stmt),
- gimple_call_arg (stmt, 0),
- gimple_call_arg (stmt, 1),
- gimple_call_arg (stmt, 2));
+ enum tree_code subcode = ERROR_MARK;
+ tree result = NULL_TREE;
+ switch (gimple_call_internal_fn (stmt))
+ {
+ case IFN_BUILTIN_EXPECT:
+ result = fold_builtin_expect (gimple_location (stmt),
+ gimple_call_arg (stmt, 0),
+ gimple_call_arg (stmt, 1),
+ gimple_call_arg (stmt, 2));
+ break;
+ 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:
+ break;
+ }
+ if (subcode != ERROR_MARK)
+ {
+ tree arg0 = gimple_call_arg (stmt, 0);
+ tree arg1 = gimple_call_arg (stmt, 1);
+ /* x = y + 0; x = y - 0; x = y * 0; */
+ if (integer_zerop (arg1))
+ result = subcode == MULT_EXPR
+ ? build_zero_cst (TREE_TYPE (arg0))
+ : arg0;
+ /* x = 0 + y; x = 0 * y; */
+ else if (subcode != MINUS_EXPR && integer_zerop (arg0))
+ result = subcode == MULT_EXPR
+ ? build_zero_cst (TREE_TYPE (arg0))
+ : arg1;
+ /* x = y - y; */
+ else if (subcode == MINUS_EXPR && operand_equal_p (arg0, arg1, 0))
+ result = build_zero_cst (TREE_TYPE (arg0));
+ /* x = y * 1; x = 1 * y; */
+ else if (subcode == MULT_EXPR)
+ {
+ if (integer_onep (arg1))
+ result = arg0;
+ else if (integer_onep (arg0))
+ result = arg1;
+ }
+ }
if (result)
{
if (!update_call_from_tree (gsi, result))
@@ -2688,15 +2731,32 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
default:
return NULL_TREE;
}
- tree op0 = (*valueize) (gimple_call_arg (stmt, 0));
- tree op1 = (*valueize) (gimple_call_arg (stmt, 1));
+ tree arg0 = gimple_call_arg (stmt, 0);
+ tree arg1 = gimple_call_arg (stmt, 1);
+ tree op0 = (*valueize) (arg0);
+ tree op1 = (*valueize) (arg1);
if (TREE_CODE (op0) != INTEGER_CST
|| TREE_CODE (op1) != INTEGER_CST)
- return NULL_TREE;
- tree res = fold_binary_loc (loc, subcode,
- TREE_TYPE (gimple_call_arg (stmt, 0)),
- op0, op1);
+ {
+ switch (subcode)
+ {
+ case MULT_EXPR:
+ /* x * 0 = 0 * x = 0 without overflow. */
+ if (integer_zerop (op0) || integer_zerop (op1))
+ return build_zero_cst (TREE_TYPE (arg0));
+ break;
+ case MINUS_EXPR:
+ /* y - y = 0 without overflow. */
+ if (operand_equal_p (op0, op1, 0))
+ return build_zero_cst (TREE_TYPE (arg0));
+ break;
+ default:
+ break;
+ }
+ }
+ tree res
+ = fold_binary_loc (loc, subcode, TREE_TYPE (arg0), op0, op1);
if (res
&& TREE_CODE (res) == INTEGER_CST
&& !TREE_OVERFLOW (res))