commit 0a6d01f7a3c0a59e5119b3ec85528b89c1129efb
Author: Kyrylo Tkachov <kyrylo.tkachov@arm.com>
Date: Wed Sep 23 15:39:32 2015 +0100
Add tree ifcombine cost gating
@@ -72,6 +72,7 @@
#include "aarch64-cost-tables.h"
#include "dumpfile.h"
#include "builtins.h"
+#include "params.h"
#include "rtl-iter.h"
#include "tm-constrs.h"
#include "sched-int.h"
@@ -7933,6 +7934,11 @@ aarch64_override_options (void)
aarch64_override_options_internal (&global_options);
+ maybe_set_param_value (PARAM_IFCOMBINE_THRESHOLD,
+ 5,
+ global_options.x_param_values,
+ global_options_set.x_param_values);
+
/* Save these options as the default ones in case we push and pop them later
while processing functions with potential target attributes. */
target_option_default_node = target_option_current_node
@@ -1041,6 +1041,12 @@ DEFPARAM (PARAM_CASE_VALUES_THRESHOLD,
"if 0, use the default for the machine",
0, 0, 0)
+DEFPARAM (PARAM_IFCOMBINE_THRESHOLD,
+ "ifcombine-threshold",
+ "The approximate cost of statements in an inner block above which "
+ "it is not deemed beneficial to if-combine it with an outer block",
+ 2, 0, 0)
+
/* Data race flags for C++0x memory model compliance. */
DEFPARAM (PARAM_ALLOW_STORE_DATA_RACES,
"allow-store-data-races",
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+foo1 (int a, int b, int c, int d)
+{
+ return a > b && b <= c && c > d;
+}
+
+int
+foo2 (int a, int b, int c, int d)
+{
+ return a > b && (b <= c && c > d);
+}
+
+/* { dg-final { scan-assembler-times "ccmp" 4 } } */
@@ -35,10 +35,12 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "cfganal.h"
#include "tree-pretty-print.h"
+#include "tree-inline.h"
#include "internal-fn.h"
#include "gimple-fold.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
+#include "params.h"
#include "tree-cfg.h"
#include "tree-pass.h"
@@ -325,6 +327,41 @@ recognize_bits_test (gcond *cond, tree *name, tree *bits, bool inv)
return true;
}
+/* Return true if the sequence GS contains only comparisons
+ and logical combinations of variables. */
+
+static bool
+gimple_seq_contains_logical_ops_p (gimple_seq gs)
+{
+ gimple_stmt_iterator gsi;
+ bool ret = true;
+
+ for (gsi = gsi_start (gs); !gsi_one_before_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ enum gimple_code code = gimple_code (stmt);
+
+ if (code == GIMPLE_DEBUG)
+ continue;
+
+ if (code != GIMPLE_ASSIGN)
+ return false;
+
+ enum tree_code tcode = gimple_assign_rhs_code (stmt);
+ if (TREE_CODE_CLASS (tcode) != tcc_comparison
+ && tcode != TRUTH_AND_EXPR
+ && tcode != TRUTH_ANDIF_EXPR
+ && tcode != TRUTH_OR_EXPR
+ && tcode != TRUTH_ORIF_EXPR
+ && tcode != BIT_AND_EXPR
+ && tcode != BIT_IOR_EXPR
+ && tcode != BIT_NOT_EXPR)
+ return false;
+ }
+
+ return ret;
+}
+
/* If-convert on a and pattern with a common else block. The inner
if is specified by its INNER_COND_BB, the outer by OUTER_COND_BB.
inner_inv, outer_inv and result_inv indicate whether the conditions
@@ -511,9 +548,31 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
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_after_labels_bb (inner_cond_bb)))
- return false;
+
+ /* We'll be pulling in the inner_cond_bb code to execute
+ unconditionally. If the inner bb is just the condition then
+ always combine. If there are more statements, only allow
+ statements that facilitate generation of conditional compare
+ operations and even then only up to a limit of
+ PARAM_IFCOMBINE_THRESHOLD. */
+ if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb
+ (inner_cond_bb)))
+ {
+ bool bb_logic_ops_and_comparisons_p
+ = gimple_seq_contains_logical_ops_p (bb_seq (inner_cond_bb));
+
+ if (!bb_logic_ops_and_comparisons_p)
+ return false;
+
+ int inner_cost
+ = estimate_num_insns_seq (bb_seq (inner_cond_bb),
+ &eni_time_weights);
+ int threshold = PARAM_VALUE (PARAM_IFCOMBINE_THRESHOLD);
+
+ if (inner_cost > threshold)
+ return false;
+ }
+
t1 = fold_build2_loc (gimple_location (inner_cond),
inner_cond_code,
boolean_type_node,