On Wed, Oct 16, 2013 at 2:12 AM, Zhenqiang Chen
<zhenqiang.c...@linaro.org> wrote:
> Hi,
>
> The patch enhances ifcombine pass to recover some non short circuit
> branches. Basically, it will do the following transformation:
>
> Case 1:
>   if (cond1)
>     if (cond2)
> ==>
>   if (cond1 && cond2)
>
> Case 2:
>   if (cond1)
>     goto L1
>   if (cond2)
>     goto L1
> ==>
>   if (cond1 || cond2)
>     goto L1
>
> Case 3:
>   if (cond1)
>     goto L1
>   else
>     goto L2
> L1:
>   if (cond2)
>     goto L2
> ==>
>   if (invert (cond1) || cond2)
>     goto L2
>
> Case 4:
>   if (cond1)
>     goto L1
>   if (cond2)
>     goto L2
> L1:
> ==>
>   if (invert (cond1) && cond2)
>     goto L2
>
> Bootstrap on X86-64 and ARM.
>
> Two new FAILs in regression tests:
> gcc.dg/uninit-pred-8_b.c
> gcc.dg/uninit-pred-9_b.c
> uninit pass should be enhanced to handle more complex conditions. Will
> submit a bug to track it and fix it later.
>
> Is it OK for trunk?

I had a much simpler change which did basically the same from 4.7 (I
can update it if people think this is a better approach).

Thanks,
Andrew Pinski


    2012-09-29  Andrew Pinski  <apin...@cavium.com>

        * tree-ssa-ifcombine.c: Include rtl.h and tm_p.h.
        (ifcombine_ifandif): Handle cases where
        maybe_fold_and_comparisons fails, combining the branches
        anyways.
        (tree_ssa_ifcombine): Inverse the order of
        the basic block walk, increases the number of combinings.
        * Makefile.in (tree-ssa-ifcombine.o): Update dependencies.

        * testsuite/gcc.dg/tree-ssa/phi-opt-2.c: Expect zero ifs as the compiler
        produces a & b now.
        * testsuite/gcc.dg/tree-ssa/phi-opt-9.c: Use a function call
        to prevent conditional move to be used.
        * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c: Remove check for
        "one or more intermediate".


>
> Thanks!
> -Zhenqiang
>
> ChangeLog:
> 2013-10-16  Zhenqiang Chen  <zhenqiang.c...@linaro.org>
>
>         * fold-const.c (simple_operand_p_2): Make it global.
>         * tree.h (simple_operand_p_2): Declare it.
>         * tree-ssa-ifcombine.c: Include rtl.h and tm_p.h.
>         (bb_has_overhead_p, generate_condition_node,
>         ifcombine_ccmp): New functions.
>         (ifcombine_fold_ifandif): New function, extracted from
>         ifcombine_ifandif.
>         (ifcombine_ifandif): Call ifcombine_ccmp.
>         (tree_ssa_ifcombine_bb): Skip optimized bb.
>
> testsuite/ChangeLog
> 2013-10-16  Zhenqiang Chen  <zhenqiang.c...@linaro.org>
>
>         * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c: New test case.
>         * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c: New test case.
>         * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c: New test case.
>         * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c: New test case.
>         * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c: New test case.
>         * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c: New test case.
>         * gcc.dg/tree-ssa/ssa-dom-thread-3.c: Updated.
commit 90434d0567109d9add1eb5583ae38df06cc6ffa1
Author: Andrew Pinski <apin...@cavium.com>
Date:   Sat Sep 29 01:29:12 2012 -0700

    2012-09-29  Andrew Pinski  <apin...@cavium.com>
    
        * tree-ssa-ifcombine.c: Include rtl.h and tm_p.h.
        (ifcombine_ifandif): Handle cases where
        maybe_fold_and_comparisons fails, combining the branches
        anyways.
        (tree_ssa_ifcombine): Inverse the order of
        the basic block walk, increases the number of combinings.
        * Makefile.in (tree-ssa-ifcombine.o): Update dependencies.
    
        * testsuite/gcc.dg/tree-ssa/phi-opt-2.c: Expect zero ifs as the compiler
        produces a & b now.
        * testsuite/gcc.dg/tree-ssa/phi-opt-9.c: Use a function call
        to prevent conditional move to be used.
        * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c: Remove check for
        "one or more intermediate".

diff --git a/gcc/ChangeLog.CAVIUM b/gcc/ChangeLog.CAVIUM
index 4739ded..8413818 100644
--- a/gcc/ChangeLog.CAVIUM
+++ b/gcc/ChangeLog.CAVIUM
@@ -1,5 +1,22 @@
 2012-09-29  Andrew Pinski  <apin...@cavium.com>
 
+       * tree-ssa-ifcombine.c: Include rtl.h and tm_p.h.
+       (ifcombine_ifandif): Handle cases where
+       maybe_fold_and_comparisons fails, combining the branches
+       anyways.
+       (tree_ssa_ifcombine): Inverse the order of
+       the basic block walk, increases the number of combinings.
+       * Makefile.in (tree-ssa-ifcombine.o): Update dependencies.
+
+       * testsuite/gcc.dg/tree-ssa/phi-opt-2.c: Expect zero ifs as the compiler
+       produces a & b now.
+       * testsuite/gcc.dg/tree-ssa/phi-opt-9.c: Use a function call
+       to prevent conditional move to be used.
+       * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c: Remove check for
+       "one or more intermediate".
+
+2012-09-29  Andrew Pinski  <apin...@cavium.com>
+
        Revert:
        2012-07-23  Andrew Pinski  <apin...@cavium.com>
 
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 172dde2..ef8cb98 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2357,7 +2357,7 @@ tree-ssa-phiprop.o : tree-ssa-phiprop.c $(CONFIG_H) 
$(SYSTEM_H) coretypes.h \
    $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
    langhooks.h $(FLAGS_H) tree-pretty-print.h gimple-pretty-print.h
 tree-ssa-ifcombine.o : tree-ssa-ifcombine.c $(CONFIG_H) $(SYSTEM_H) \
-   coretypes.h $(TM_H) $(TREE_H) $(BASIC_BLOCK_H) \
+   coretypes.h $(TM_H) $(RTL_H) $(TM_P_H) $(TREE_H) $(BASIC_BLOCK_H) \
    $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
    tree-pretty-print.h
 tree-merge-const-bfstores.o : tree-merge-const-bfstores.c $(CONFIG_H) \
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 6c680be..89c76d9 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2428,7 +2428,6 @@ typedef struct mips_args {
    1 is the default; other values are interpreted relative to that.  */
 
 #define BRANCH_COST(speed_p, predictable_p) mips_branch_cost
-#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
 
 /* If defined, modifies the length assigned to instruction INSN as a
    function of the context in which it is used.  LENGTH is an lvalue
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-2.c
index 415c117..26952ac 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-2.c
@@ -13,10 +13,7 @@ _Bool f1(_Bool a, _Bool b)
   return 0;
 }
 
-
-/* There should be only one if, the outer one; the inner one
-   should have been changed to straight line code with the
-   value of b (except that we don't fold ! (b != 0) into b
-   which can be fixed in a different patch).  */
-/* { dg-final { scan-tree-dump-times "if" 1 "optimized"} } */
+/* There should be only no ifs; both of them should have
+   been changed into straight line code (a & b).  */
+/* { dg-final { scan-tree-dump-times "if" 0 "optimized"} } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c 
b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c
index dccea7b..a224788 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c
@@ -2,13 +2,14 @@
 /* { dg-options "-O -fdump-tree-optimized" } */
 
 int g(int,int);
+int h(int);
 int f(int t, int c)
 {
   int d = 0;
   int e = 0;
   if (t)
     {
-      d = c+1;
+      d = h(c);
       e = t;
     }
   else d = 0, e = 0;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c
index d851bf2..8fb3ef8 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c
@@ -42,6 +42,5 @@ expand_one_var (tree var, unsigned char toplevel, unsigned 
char really_expand)
 }
 /* We should thread the jump, through an intermediate block.  */
 /* { dg-final { scan-tree-dump-times "Threaded" 1 "dom1"} } */
-/* { dg-final { scan-tree-dump-times "one or more intermediate" 1 "dom1"} } */
 /* { dg-final { cleanup-tree-dump "dom1" } } */
 
diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c
index 4e6075b..6e18ec8 100644
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -22,6 +22,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+/* rtl is needed only because arm back-end requires it for
+   BRANCH_COST.  */
+#include "rtl.h"
+#include "tm_p.h"
 #include "tree.h"
 #include "basic-block.h"
 #include "timevar.h"
@@ -30,6 +34,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "tree-dump.h"
 
+#ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
+#define LOGICAL_OP_NON_SHORT_CIRCUIT \
+  (BRANCH_COST (optimize_function_for_speed_p (cfun), \
+                false) >= 2)
+#endif
+
 /* This pass combines COND_EXPRs to simplify control flow.  It
    currently recognizes bit tests and comparisons in chains that
    represent logical and or logical or of two COND_EXPRs.
@@ -486,7 +496,30 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
                                            outer_cond_code,
                                            gimple_cond_lhs (outer_cond),
                                            gimple_cond_rhs (outer_cond))))
-       return false;
+       {
+         tree t1, t2;
+         gimple_stmt_iterator gsi;
+         if (!LOGICAL_OP_NON_SHORT_CIRCUIT)
+           return false;
+         /* Only do this optimization if the inner bb contains only the 
conditional. */
+         if (!gsi_one_before_end_p (gsi_start_nondebug_bb (inner_cond_bb)))
+           return false;
+         t1 = fold_build2_loc (gimple_location (inner_cond),
+                               inner_cond_code,
+                               boolean_type_node,
+                               gimple_cond_lhs (inner_cond),
+                               gimple_cond_rhs (inner_cond));
+         t2 = fold_build2_loc (gimple_location (outer_cond),
+                               outer_cond_code,
+                               boolean_type_node,
+                               gimple_cond_lhs (outer_cond),
+                               gimple_cond_rhs (outer_cond));
+         t = fold_build2_loc (gimple_location (inner_cond), 
+                              TRUTH_AND_EXPR, boolean_type_node, t1, t2);
+         gsi = gsi_for_stmt (inner_cond);
+         t = force_gimple_operand_gsi (&gsi, t, true, NULL, true,
+                                       GSI_SAME_STMT);
+        }
       if (result_inv)
        t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
       t = canonicalize_cond_expr_cond (t);
@@ -629,7 +662,7 @@ tree_ssa_ifcombine (void)
   bbs = blocks_in_phiopt_order ();
   calculate_dominance_info (CDI_DOMINATORS);
 
-  for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; ++i)
+  for (i = n_basic_blocks - NUM_FIXED_BLOCKS -1; i >= 0; i--)
     {
       basic_block bb = bbs[i];
       gimple stmt = last_stmt (bb);

Reply via email to