aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c86
1 files changed, 74 insertions, 12 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 73f090b..1d8fd74 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see
#include "varasm.h"
#include "memmodel.h"
#include "optabs.h"
+#include "internal-fn.h"
enum strlen_range_kind {
/* Compute the exact constant string length. */
@@ -2993,7 +2994,6 @@ gimple_fold_builtin_fputs (gimple_stmt_iterator *gsi,
default:
gcc_unreachable ();
}
- return false;
}
/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
@@ -5776,18 +5776,19 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{
gcc_assert (res_op->code.is_tree_code ());
- if (TREE_CODE_CLASS ((enum tree_code) res_op->code) == tcc_comparison
+ auto code = tree_code (res_op->code);
+ if (TREE_CODE_CLASS (code) == tcc_comparison
/* GIMPLE_CONDs condition may not throw. */
&& (!flag_exceptions
|| !cfun->can_throw_non_call_exceptions
- || !operation_could_trap_p (res_op->code,
+ || !operation_could_trap_p (code,
FLOAT_TYPE_P (TREE_TYPE (ops[0])),
false, NULL_TREE)))
- gimple_cond_set_condition (cond_stmt, res_op->code, ops[0], ops[1]);
- else if (res_op->code == SSA_NAME)
+ gimple_cond_set_condition (cond_stmt, code, ops[0], ops[1]);
+ else if (code == SSA_NAME)
gimple_cond_set_condition (cond_stmt, NE_EXPR, ops[0],
build_zero_cst (TREE_TYPE (ops[0])));
- else if (res_op->code == INTEGER_CST)
+ else if (code == INTEGER_CST)
{
if (integer_zerop (ops[0]))
gimple_cond_make_false (cond_stmt);
@@ -5818,11 +5819,12 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
else if (is_gimple_assign (stmt)
&& res_op->code.is_tree_code ())
{
+ auto code = tree_code (res_op->code);
if (!inplace
- || gimple_num_ops (stmt) > get_gimple_rhs_num_ops (res_op->code))
+ || gimple_num_ops (stmt) > get_gimple_rhs_num_ops (code))
{
maybe_build_generic_op (res_op);
- gimple_assign_set_rhs_with_ops (gsi, res_op->code,
+ gimple_assign_set_rhs_with_ops (gsi, code,
res_op->op_or_null (0),
res_op->op_or_null (1),
res_op->op_or_null (2));
@@ -5839,7 +5841,7 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi,
}
}
else if (res_op->code.is_fn_code ()
- && gimple_call_combined_fn (stmt) == res_op->code)
+ && gimple_call_combined_fn (stmt) == combined_fn (res_op->code))
{
gcc_assert (num_ops == gimple_call_num_args (stmt));
for (unsigned int i = 0; i < num_ops; ++i)
@@ -6108,18 +6110,36 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
break;
case GIMPLE_CALL:
{
- for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ gcall *call = as_a<gcall *> (stmt);
+ for (i = 0; i < gimple_call_num_args (call); ++i)
{
- tree *arg = gimple_call_arg_ptr (stmt, i);
+ tree *arg = gimple_call_arg_ptr (call, i);
if (REFERENCE_CLASS_P (*arg)
&& maybe_canonicalize_mem_ref_addr (arg))
changed = true;
}
- tree *lhs = gimple_call_lhs_ptr (stmt);
+ tree *lhs = gimple_call_lhs_ptr (call);
if (*lhs
&& REFERENCE_CLASS_P (*lhs)
&& maybe_canonicalize_mem_ref_addr (lhs))
changed = true;
+ if (*lhs)
+ {
+ combined_fn cfn = gimple_call_combined_fn (call);
+ internal_fn ifn = associated_internal_fn (cfn, TREE_TYPE (*lhs));
+ int opno = first_commutative_argument (ifn);
+ if (opno >= 0)
+ {
+ tree arg1 = gimple_call_arg (call, opno);
+ tree arg2 = gimple_call_arg (call, opno + 1);
+ if (tree_swap_operands_p (arg1, arg2))
+ {
+ gimple_call_set_arg (call, opno, arg2);
+ gimple_call_set_arg (call, opno + 1, arg1);
+ changed = true;
+ }
+ }
+ }
break;
}
case GIMPLE_ASM:
@@ -8776,6 +8796,48 @@ gimple_build (gimple_seq *seq, location_t loc, combined_fn fn,
return res;
}
+/* Build CODE (OP0) with a result of type TYPE (or no result if TYPE is
+ void) with location LOC, simplifying it first if possible. Returns the
+ built expression value (or NULL_TREE if TYPE is void) and appends
+ statements possibly defining it to SEQ. */
+
+tree
+gimple_build (gimple_seq *seq, location_t loc, code_helper code,
+ tree type, tree op0)
+{
+ if (code.is_tree_code ())
+ return gimple_build (seq, loc, tree_code (code), type, op0);
+ return gimple_build (seq, loc, combined_fn (code), type, op0);
+}
+
+/* Build CODE (OP0, OP1) with a result of type TYPE (or no result if TYPE is
+ void) with location LOC, simplifying it first if possible. Returns the
+ built expression value (or NULL_TREE if TYPE is void) and appends
+ statements possibly defining it to SEQ. */
+
+tree
+gimple_build (gimple_seq *seq, location_t loc, code_helper code,
+ tree type, tree op0, tree op1)
+{
+ if (code.is_tree_code ())
+ return gimple_build (seq, loc, tree_code (code), type, op0, op1);
+ return gimple_build (seq, loc, combined_fn (code), type, op0, op1);
+}
+
+/* Build CODE (OP0, OP1, OP2) with a result of type TYPE (or no result if TYPE
+ is void) with location LOC, simplifying it first if possible. Returns the
+ built expression value (or NULL_TREE if TYPE is void) and appends statements
+ possibly defining it to SEQ. */
+
+tree
+gimple_build (gimple_seq *seq, location_t loc, code_helper code,
+ tree type, tree op0, tree op1, tree op2)
+{
+ if (code.is_tree_code ())
+ return gimple_build (seq, loc, tree_code (code), type, op0, op1, op2);
+ return gimple_build (seq, loc, combined_fn (code), type, op0, op1, op2);
+}
+
/* Build the conversion (TYPE) OP with a result of type TYPE
with location LOC if such conversion is neccesary in GIMPLE,
simplifying it first.