@@ -76,6 +76,8 @@
#include "sched-int.h"
#include "cortex-a57-fma-steering.h"
#include "target-globals.h"
+#include "ifcvt.h"
+#include "math.h"
/* This file should be included last. */
#include "target-def.h"
@@ -13362,6 +13364,7 @@ aarch64_unspec_may_trap_p (const_rtx x, unsigned flags)
return default_unspec_may_trap_p (x, flags);
}
+
/* Implement TARGET_PROMOTED_TYPE to promote __fp16 to float. */
static tree
aarch64_promoted_type (const_tree t)
@@ -13370,6 +13373,117 @@ aarch64_promoted_type (const_tree t)
return float_type_node;
return NULL_TREE;
}
+
+/* Get an additional cost roughly mapping to the cycles cost of a
+ mispredicted branch, scaled by how predictable we think that branch
+ is. Note that in the AArch64 back-end we try to map COSTS_N_INSNS (1)
+ to the latency of the cheapest instruction, with other instructions
+ scaled from that.
+
+ PREDICTABILITY is derived from the computed branch taken probability
+ and will be in the range [0..1], where 0.0 is a branch which should be
+ considered unpredictable, and 1.0 is a branch which is predictable.
+
+ Branches which are more predictable are less profitable to if-convert and
+ should return smaller values. Branches which are more predictable are more
+ profitable to if-convert and should return higher values.
+
+ FORNOW: use math.h's log2 and take and return floats.
+ TODO: Design a function which gives more meaningful results. */
+
+static float
+aarch64_additional_branch_cost_for_probability (float predictability)
+{
+ /* Scale to be in range [1..2], then take log2 of it. Use this to
+ pick a point between two -mcpu (well, one day) dependent values. */
+ unsigned int lower_bound = COSTS_N_INSNS (2);
+ unsigned int upper_bound = COSTS_N_INSNS (6);
+
+ return log2 (predictability + 1.0f)
+ * (upper_bound - lower_bound) + lower_bound;
+}
+
+/* Prototype only, return TRUE if SEQ is a profitable transformation of
+ the basic block structure defined in IF_INFO.
+
+ TODO: Design and analyze how this function should actually behave.
+ This is just guesswork. */
+
+static bool
+aarch64_ifcvt_noce_profitable_p (rtx_insn *seq,
+ struct noce_if_info *if_info)
+{
+ bool speed_p
+ = optimize_bb_for_speed_p (if_info->test_bb);
+
+ float sequence_cost (seq_cost (seq, speed_p));
+
+ /* We know that when expanding an if-convert sequence for AArch64 we
+ will generate a number of redundant comparisons. Account for that
+ by slightly modifying the numbers. */
+ sequence_cost /= 1.5f;
+
+ float then_cost (if_info->then_cost);
+ float else_cost = 0.0;
+
+ if (if_info->else_bb)
+ else_cost = if_info->else_cost;
+
+ /* Get the weighting factors. */
+ edge te = EDGE_SUCC (if_info->test_bb, 0);
+ float taken_probability = ((float) te->probability) / REG_BR_PROB_BASE;
+
+ /* We have to reverse the branch taken probability if we have a
+ then_else_reversed branch structure. We want to get this correct
+ so we scale the cost of the correct branch. */
+ if (if_info->then_else_reversed)
+ taken_probability = 1.0f - taken_probability;
+
+ /* For branch_probability, we don't care which branch we are
+ considering, we just need a value in the range [0..0.5]. */
+ float branch_probability = taken_probability;
+ if (branch_probability > 0.5f)
+ branch_probability = 1.0f - branch_probability;
+
+ /* Taken_probability is in range [0.0..0.5]. Scale to be in
+ range [0.0..1.0], and subtract from 1.0 so a taken_probability of 0.5
+ gives a predictability of 0.0. */
+ float predictability = 1.0 - (2.0 * branch_probability);
+
+ float weighted_average_cost = ((taken_probability
+ * (then_cost - else_cost)) + then_cost);
+
+ if (!if_info->else_bb)
+ weighted_average_cost /= 2.0f;
+ float branch_cost
+ = aarch64_additional_branch_cost_for_probability (predictability);
+
+ float estimate_unconverted_cost = weighted_average_cost + branch_cost;
+
+ bool judgement = sequence_cost <= estimate_unconverted_cost;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n AArch64 cost calculations for if-conversion:\n"
+ " taken probability %f\n"
+ " then block cost %f\n"
+ " else block cost %f\n"
+ " weighted average cost %f\n"
+ " additional branch cost %f\n"
+ " total unconverted cost %f\n"
+ " new sequence cost %f\n"
+ "\n Judgement: %s\n",
+ taken_probability, then_cost, else_cost,
+ weighted_average_cost, branch_cost,
+ estimate_unconverted_cost, sequence_cost,
+ judgement
+ ? "Convert"
+ : "Do not convert");
+ }
+
+ return judgement;
+}
+
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST aarch64_address_cost
@@ -13674,6 +13788,10 @@ aarch64_promoted_type (const_tree t)
#undef TARGET_USE_PSEUDO_PIC_REG
#define TARGET_USE_PSEUDO_PIC_REG aarch64_use_pseudo_pic_reg
+#undef TARGET_COSTS_IFCVT_NOCE_PROFITABLE_P
+#define TARGET_COSTS_IFCVT_NOCE_PROFITABLE_P \
+ aarch64_ifcvt_noce_profitable_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-aarch64.h"