GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
return true;
}
+/* Return the best representative SSA name for CANDIDATE which is used
+ in a bit test. */
+
+static tree
+get_name_for_bit_test (tree candidate)
+{
+ /* Skip single-use names in favor of using the name from a
+ non-widening conversion definition. */
+ if (TREE_CODE (candidate) == SSA_NAME
+ && has_single_use (candidate))
+ {
+ tree def_stmt = SSA_NAME_DEF_STMT (candidate);
+ if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT
+ && CONVERT_EXPR_P (GIMPLE_STMT_OPERAND (def_stmt, 1)))
+ {
+ tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ if (TYPE_PRECISION (TREE_TYPE (rhs))
+ <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (rhs, 0))))
+ return TREE_OPERAND (rhs, 0);
+ }
+ }
+
+ return candidate;
+}
+
/* Recognize a single bit test pattern in COND_EXPR and its defining
statements. Store the name being tested in *NAME and the bit
in *BIT. The COND_EXPR computes *NAME & (1 << *BIT).
&& integer_onep (TREE_OPERAND (t, 1))
&& TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME)
{
- t = TREE_OPERAND (t, 0);
+ tree orig_name = TREE_OPERAND (t, 0);
+
+ /* Look through copies and conversions to eventually
+ find the stmt that computes the shift. */
+ t = orig_name;
do {
t = SSA_NAME_DEF_STMT (t);
if (TREE_CODE (t) != GIMPLE_MODIFY_STMT)
- return false;
+ break;
t = GIMPLE_STMT_OPERAND (t, 1);
- if (TREE_CODE (t) == NOP_EXPR
- || TREE_CODE (t) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (t))
t = TREE_OPERAND (t, 0);
} while (TREE_CODE (t) == SSA_NAME);
+ /* If we found such, decompose it. */
if (TREE_CODE (t) == RSHIFT_EXPR)
{
/* op0 & (1 << op1) */
else
{
/* t & 1 */
- *bit = integer_one_node;
- *name = t;
+ *bit = integer_zero_node;
+ *name = get_name_for_bit_test (orig_name);
}
return true;
if (TREE_CODE (t) != BIT_AND_EXPR)
return false;
- *name = TREE_OPERAND (t, 0);
+ *name = get_name_for_bit_test (TREE_OPERAND (t, 0));
*bits = TREE_OPERAND (t, 1);
return true;
/* Do it. */
bsi = bsi_for_stmt (inner_cond);
t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
- integer_one_node, bit1);
+ build_int_cst (TREE_TYPE (name1), 1), bit1);
t2 = fold_build2 (LSHIFT_EXPR, TREE_TYPE (name1),
- integer_one_node, bit2);
+ build_int_cst (TREE_TYPE (name1), 1), bit2);
t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), t, t2);
- t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE);
+ t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE,
+ true, BSI_SAME_STMT);
t2 = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
- t2 = force_gimple_operand_bsi (&bsi, t2, true, NULL_TREE);
+ t2 = force_gimple_operand_bsi (&bsi, t2, true, NULL_TREE,
+ true, BSI_SAME_STMT);
COND_EXPR_COND (inner_cond) = fold_build2 (EQ_EXPR, boolean_type_node,
t2, t);
update_stmt (inner_cond);
/* Do it. */
bsi = bsi_for_stmt (inner_cond);
t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), bits1, bits2);
- t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE);
+ t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE,
+ true, BSI_SAME_STMT);
t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t);
- t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE);
+ t = force_gimple_operand_bsi (&bsi, t, true, NULL_TREE,
+ true, BSI_SAME_STMT);
COND_EXPR_COND (inner_cond) = fold_build2 (NE_EXPR, boolean_type_node, t,
build_int_cst (TREE_TYPE (t), 0));
update_stmt (inner_cond);
/* Do it. */
t = fold_build2 (code, boolean_type_node,
TREE_OPERAND (ccond2, 0), TREE_OPERAND (ccond2, 1));
+ t = canonicalize_cond_expr_cond (t);
+ if (!t)
+ return false;
COND_EXPR_COND (inner_cond) = t;
update_stmt (inner_cond);
return 1;
}
-struct tree_opt_pass pass_tree_ifcombine = {
+struct gimple_opt_pass pass_tree_ifcombine =
+{
+ {
+ GIMPLE_PASS,
"ifcombine", /* name */
gate_ifcombine, /* gate */
tree_ssa_ifcombine, /* execute */
TODO_dump_func
| TODO_ggc_collect
| TODO_update_ssa
- | TODO_verify_ssa, /* todo_flags_finish */
- 0 /* letter */
+ | TODO_verify_ssa /* todo_flags_finish */
+ }
};