summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c12
-rw-r--r--gcc/tree-ssa-phiopt.c115
5 files changed, 129 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a294e940cfe..06df3c2d483 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2004-05-18 Andrew Pinski <pinskia@physics.uc.edu>
+ Jeff Law <law@redhat.com>
+
+ * Makefile.in (tree-ssa-phiopt.o): Depends on flags.h.
+ * tree-ssa-phiopt.c: Include flags.h.
+ (conditional_replacement): Remove argument names from prototype.
+ Minor formatting and comment fixes.
+ (tree_ssa_phiopt): If conditional_replacement returns false, then
+ call value_replacement.
+ (value_replacement): New function.
+
2004-05-18 Jeff Law <law@redhat.com>
* tree-ssa-phiopt.c (replace_phi_with_stmt): New function extracted
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 39fbe32f854..804aa5ea88a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1581,7 +1581,7 @@ tree-ssa-forwprop.o : tree-ssa-forwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H)
tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) errors.h $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
- $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) langhooks.h
+ $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) langhooks.h flags.h
tree-nrv.o : tree-nrv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(RTL_H) function.h $(BASIC_BLOCK_H) $(EXPR_H) \
diagnostic.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TREE_DUMP_H) tree-pass.h \
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 911b84092b9..fcf983fbd7d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-05-18 Andrew Pinski <pinskia@physics.uc.edu>
+
+ * gcc.dg/tree-ssa/20040518-1.c: New test.
+
2004-05-18 Zack Weinberg <zack@codesourcery.com>
* gcc.c-torture/execute/991216-3.c: Delete, duplicate of 991216-2.c.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c
new file mode 100644
index 00000000000..f80a74a14ea
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-phiopt1-details" } */
+int f(int a, int b)
+{
+ int c = b;
+ if (a != b)
+ c = a;
+ return c;
+}
+
+/* Should have no ifs left after straightening. */
+/* { dg-final { scan-tree-dump-times "if " 0 "phiopt1"} } */
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index a29b8f71a94..bc339c808bf 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -26,6 +26,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "tree.h"
#include "rtl.h"
+#include "flags.h"
#include "tm_p.h"
#include "basic-block.h"
#include "timevar.h"
@@ -36,15 +37,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "langhooks.h"
static void tree_ssa_phiopt (void);
-static bool conditional_replacement (basic_block bb, tree phi, tree arg0,
- tree arg1);
+static bool conditional_replacement (basic_block, tree, tree, tree);
+static bool value_replacement (basic_block, tree, tree, tree);
static void replace_phi_with_stmt (block_stmt_iterator, basic_block,
basic_block, tree, tree);
static bool candidate_bb_for_phi_optimization (basic_block,
basic_block *,
basic_block *);
-
/* This pass eliminates PHI nodes which can be trivially implemented as
an assignment from a conditional expression. ie if we have something
like:
@@ -64,7 +64,25 @@ static bool candidate_bb_for_phi_optimization (basic_block,
bb1 will become unreachable and bb0 and bb2 will almost always
be merged into a single block. This occurs often due to gimplification
- of conditionals. */
+ of conditionals.
+
+ Also done is the following optimization:
+
+ bb0:
+ if (a != b) goto bb2; else goto bb1;
+ bb1:
+ bb2:
+ x = PHI (a (bb1), b (bb0))
+
+ We can rewrite that as:
+
+ bb0:
+ bb1:
+ bb2:
+ x = b;
+
+ This can sometimes occur as a result of other optimizations. A
+ similar transformation is done by the ifcvt RTL optimizer. */
static void
tree_ssa_phiopt (void)
@@ -77,7 +95,6 @@ tree_ssa_phiopt (void)
{
tree arg0, arg1, phi;
-
/* We're searching for blocks with one PHI node which has two
arguments. */
phi = phi_nodes (bb);
@@ -88,12 +105,13 @@ tree_ssa_phiopt (void)
arg1 = PHI_ARG_DEF (phi, 1);
/* Do the replacement of conditional if it can be done. */
- if (conditional_replacement (bb, phi, arg0, arg1))
- {
- /* We have done the replacement so we need to rebuild the cfg. */
- removed_phis = true;
- continue;
- }
+ if (conditional_replacement (bb, phi, arg0, arg1)
+ || value_replacement (bb, phi, arg0, arg1))
+ {
+ /* We have done the replacement so we need to rebuild the
+ cfg when this pass is complete. */
+ removed_phis = true;
+ }
}
}
@@ -294,8 +312,7 @@ conditional_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
TREE_OPERAND (old_result, 0),
TREE_OPERAND (old_result, 1));
- new1 = build (MODIFY_EXPR, TREE_TYPE (result),
- new_var, new1);
+ new1 = build (MODIFY_EXPR, TREE_TYPE (result), new_var, new1);
bsi_insert_after (&bsi, new1, BSI_NEW_STMT);
}
@@ -330,7 +347,7 @@ conditional_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
cond = cond1;
/* If what we get back is a conditional expression, there is no
- way that is can be gimple. */
+ way that it can be gimple. */
if (TREE_CODE (cond) == COND_EXPR)
return false;
@@ -360,6 +377,76 @@ conditional_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
return true;
}
+/* The function value_replacement does the main work of doing the value
+ replacement. Return true if the replacement is done. Otherwise return
+ false.
+ BB is the basic block where the replacement is going to be done on. ARG0
+ is argument 0 from the PHI. Likewise for ARG1. */
+
+static bool
+value_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
+{
+ tree result;
+ basic_block other_block = NULL;
+ basic_block cond_block = NULL;
+ tree new, cond;
+ edge true_edge, false_edge;
+
+ /* If the type says honor signed zeros we cannot do this
+ optimization. */
+ if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
+ return false;
+
+ if (!candidate_bb_for_phi_optimization (bb, &cond_block, &other_block))
+ return false;
+
+ cond = COND_EXPR_COND (last_stmt (cond_block));
+ result = PHI_RESULT (phi);
+
+ /* This transformation is only valid for equality comparisons. */
+ if (TREE_CODE (cond) != NE_EXPR && TREE_CODE (cond) != EQ_EXPR)
+ return false;
+
+ /* We need to know which is the true edge and which is the false
+ edge so that we know if have abs or negative abs. */
+ extract_true_false_edges_from_block (cond_block, &true_edge, &false_edge);
+
+ /* At this point we know we have a COND_EXPR with two successors.
+ One successor is BB, the other successor is an empty block which
+ falls through into BB.
+
+ The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR.
+
+ There is a single PHI node at the join point (BB) with two arguments.
+
+ We now need to verify that the two arguments in the PHI node match
+ the two arguments to the equality comparison. */
+
+ if ((operand_equal_p (arg0, TREE_OPERAND (cond, 0), 0)
+ && operand_equal_p (arg1, TREE_OPERAND (cond, 1), 0))
+ || (operand_equal_p (arg1, TREE_OPERAND (cond, 0), 0)
+ && operand_equal_p (arg0, TREE_OPERAND (cond, 1), 0)))
+ {
+ edge e;
+ tree arg;
+
+ e = (TREE_CODE (cond) == NE_EXPR ? true_edge : false_edge);
+ if (PHI_ARG_EDGE (phi, 0) == e)
+ arg = arg0;
+ else
+ arg = arg1;
+
+ /* Build the new assignment. */
+ new = build (MODIFY_EXPR, TREE_TYPE (result), result, arg);
+
+ replace_phi_with_stmt (bsi_start (bb), bb, cond_block, phi, new);
+
+ /* Note that we optimized this PHI. */
+ return true;
+ }
+ return false;
+}
+
/* Always do these optimizations if we have SSA
trees to work on. */