tree decl = builtin_decl_implicit (rcode);
if (!decl)
return NULL_TREE;
- unsigned nargs = type_num_arguments (TREE_TYPE (decl));
- gcc_assert (nargs <= 3);
/* Play safe and do not allow abnormals to be mentioned in
newly created statements. */
- if ((TREE_CODE (ops[0]) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[0]))
- || (nargs >= 2
- && TREE_CODE (ops[1]) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[1]))
- || (nargs == 3
- && TREE_CODE (ops[2]) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[2])))
- return NULL_TREE;
+ unsigned nargs;
+ for (nargs = 0; nargs < 3; ++nargs)
+ {
+ if (!ops[nargs])
+ break;
+ if (TREE_CODE (ops[nargs]) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[nargs]))
+ return NULL_TREE;
+ }
+ gcc_assert (nargs != 0);
if (!res)
res = make_ssa_name (type);
gimple new_stmt = gimple_build_call (decl, nargs, ops[0], ops[1], ops[2]);
return maybe_push_res_to_seq (rcode, type, ops, seq);
}
+/* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
+ VALUEIZED to true if valueization changed OP. */
+
+static inline tree
+do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
+{
+ if (valueize && TREE_CODE (op) == SSA_NAME)
+ {
+ tree tem = valueize (op);
+ if (tem && tem != op)
+ {
+ op = tem;
+ valueized = true;
+ }
+ }
+ return op;
+}
/* The main STMT based simplification entry. It is used by the fold_stmt
and the fold_stmt_to_constant APIs. */
|| code == VIEW_CONVERT_EXPR)
{
tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
- if (top_valueize && TREE_CODE (op0) == SSA_NAME)
- {
- tree tem = top_valueize (op0);
- if (tem)
- op0 = tem;
- }
+ bool valueized = false;
+ op0 = do_valueize (op0, top_valueize, valueized);
*rcode = code;
ops[0] = op0;
- return gimple_resimplify1 (seq, rcode, type, ops, valueize);
+ return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
+ || valueized);
}
else if (code == BIT_FIELD_REF)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
tree op0 = TREE_OPERAND (rhs1, 0);
- if (top_valueize && TREE_CODE (op0) == SSA_NAME)
- {
- tree tem = top_valueize (op0);
- if (tem)
- op0 = tem;
- }
+ bool valueized = false;
+ op0 = do_valueize (op0, top_valueize, valueized);
*rcode = code;
ops[0] = op0;
ops[1] = TREE_OPERAND (rhs1, 1);
ops[2] = TREE_OPERAND (rhs1, 2);
- return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+ return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
+ || valueized);
}
else if (code == SSA_NAME
&& top_valueize)
case GIMPLE_UNARY_RHS:
{
tree rhs1 = gimple_assign_rhs1 (stmt);
- if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
- {
- tree tem = top_valueize (rhs1);
- if (tem)
- rhs1 = tem;
- }
+ bool valueized = false;
+ rhs1 = do_valueize (rhs1, top_valueize, valueized);
*rcode = code;
ops[0] = rhs1;
- return gimple_resimplify1 (seq, rcode, type, ops, valueize);
+ return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
+ || valueized);
}
case GIMPLE_BINARY_RHS:
{
tree rhs1 = gimple_assign_rhs1 (stmt);
- if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
- {
- tree tem = top_valueize (rhs1);
- if (tem)
- rhs1 = tem;
- }
tree rhs2 = gimple_assign_rhs2 (stmt);
- if (top_valueize && TREE_CODE (rhs2) == SSA_NAME)
- {
- tree tem = top_valueize (rhs2);
- if (tem)
- rhs2 = tem;
- }
+ bool valueized = false;
+ rhs1 = do_valueize (rhs1, top_valueize, valueized);
+ rhs2 = do_valueize (rhs2, top_valueize, valueized);
*rcode = code;
ops[0] = rhs1;
ops[1] = rhs2;
- return gimple_resimplify2 (seq, rcode, type, ops, valueize);
+ return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
+ || valueized);
}
case GIMPLE_TERNARY_RHS:
{
tree rhs1 = gimple_assign_rhs1 (stmt);
- if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
- {
- tree tem = top_valueize (rhs1);
- if (tem)
- rhs1 = tem;
- }
tree rhs2 = gimple_assign_rhs2 (stmt);
- if (top_valueize && TREE_CODE (rhs2) == SSA_NAME)
- {
- tree tem = top_valueize (rhs2);
- if (tem)
- rhs2 = tem;
- }
tree rhs3 = gimple_assign_rhs3 (stmt);
- if (top_valueize && TREE_CODE (rhs3) == SSA_NAME)
- {
- tree tem = top_valueize (rhs3);
- if (tem)
- rhs3 = tem;
- }
+ bool valueized = false;
+ rhs1 = do_valueize (rhs1, top_valueize, valueized);
+ rhs2 = do_valueize (rhs2, top_valueize, valueized);
+ rhs3 = do_valueize (rhs3, top_valueize, valueized);
*rcode = code;
ops[0] = rhs1;
ops[1] = rhs2;
ops[2] = rhs3;
- return gimple_resimplify3 (seq, rcode, type, ops, valueize);
+ return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
+ || valueized);
}
default:
gcc_unreachable ();
case GIMPLE_CALL:
/* ??? This way we can't simplify calls with side-effects. */
- if (gimple_call_lhs (stmt) != NULL_TREE)
+ if (gimple_call_lhs (stmt) != NULL_TREE
+ && gimple_call_num_args (stmt) >= 1
+ && gimple_call_num_args (stmt) <= 3)
{
tree fn = gimple_call_fn (stmt);
/* ??? Internal function support missing. */
if (!fn)
return false;
- if (top_valueize && TREE_CODE (fn) == SSA_NAME)
- {
- tree tem = top_valueize (fn);
- if (tem)
- fn = tem;
- }
- if (!fn
- || TREE_CODE (fn) != ADDR_EXPR
- || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL
- || DECL_BUILT_IN_CLASS (TREE_OPERAND (fn, 0)) != BUILT_IN_NORMAL
- || !builtin_decl_implicit (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)))
- || !gimple_builtin_call_types_compatible_p (stmt,
- TREE_OPERAND (fn, 0)))
+ bool valueized = false;
+ fn = do_valueize (fn, top_valueize, valueized);
+ if (TREE_CODE (fn) != ADDR_EXPR
+ || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
return false;
tree decl = TREE_OPERAND (fn, 0);
+ if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
+ || !builtin_decl_implicit (DECL_FUNCTION_CODE (decl))
+ || !gimple_builtin_call_types_compatible_p (stmt, decl))
+ return false;
+
tree type = TREE_TYPE (gimple_call_lhs (stmt));
+ *rcode = DECL_FUNCTION_CODE (decl);
+ for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
+ {
+ tree arg = gimple_call_arg (stmt, i);
+ ops[i] = do_valueize (arg, top_valueize, valueized);
+ }
switch (gimple_call_num_args (stmt))
{
case 1:
- {
- tree arg1 = gimple_call_arg (stmt, 0);
- if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
- {
- tree tem = top_valueize (arg1);
- if (tem)
- arg1 = tem;
- }
- *rcode = DECL_FUNCTION_CODE (decl);
- ops[0] = arg1;
- return gimple_resimplify1 (seq, rcode, type, ops, valueize);
- }
+ return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
+ || valueized);
case 2:
- {
- tree arg1 = gimple_call_arg (stmt, 0);
- if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
- {
- tree tem = top_valueize (arg1);
- if (tem)
- arg1 = tem;
- }
- tree arg2 = gimple_call_arg (stmt, 1);
- if (top_valueize && TREE_CODE (arg2) == SSA_NAME)
- {
- tree tem = top_valueize (arg2);
- if (tem)
- arg2 = tem;
- }
- *rcode = DECL_FUNCTION_CODE (decl);
- ops[0] = arg1;
- ops[1] = arg2;
- return gimple_resimplify2 (seq, rcode, type, ops, valueize);
- }
+ return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
+ || valueized);
case 3:
- {
- tree arg1 = gimple_call_arg (stmt, 0);
- if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
- {
- tree tem = top_valueize (arg1);
- if (tem)
- arg1 = tem;
- }
- tree arg2 = gimple_call_arg (stmt, 1);
- if (top_valueize && TREE_CODE (arg2) == SSA_NAME)
- {
- tree tem = top_valueize (arg2);
- if (tem)
- arg2 = tem;
- }
- tree arg3 = gimple_call_arg (stmt, 2);
- if (top_valueize && TREE_CODE (arg3) == SSA_NAME)
- {
- tree tem = top_valueize (arg3);
- if (tem)
- arg3 = tem;
- }
- *rcode = DECL_FUNCTION_CODE (decl);
- ops[0] = arg1;
- ops[1] = arg2;
- ops[2] = arg3;
- return gimple_resimplify3 (seq, rcode, type, ops, valueize);
- }
+ return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
+ || valueized);
default:
- return false;
+ gcc_unreachable ();
}
}
break;
case GIMPLE_COND:
{
tree lhs = gimple_cond_lhs (stmt);
- if (top_valueize && TREE_CODE (lhs) == SSA_NAME)
- {
- tree tem = top_valueize (lhs);
- if (tem)
- lhs = tem;
- }
tree rhs = gimple_cond_rhs (stmt);
- if (top_valueize && TREE_CODE (rhs) == SSA_NAME)
- {
- tree tem = top_valueize (rhs);
- if (tem)
- rhs = tem;
- }
+ bool valueized = false;
+ lhs = do_valueize (lhs, top_valueize, valueized);
+ rhs = do_valueize (rhs, top_valueize, valueized);
*rcode = gimple_cond_code (stmt);
ops[0] = lhs;
ops[1] = rhs;
- return gimple_resimplify2 (seq, rcode, boolean_type_node, ops, valueize);
+ return (gimple_resimplify2 (seq, rcode,
+ boolean_type_node, ops, valueize)
+ || valueized);
}
default: