aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorAndre Vieira <andre.simoesdiasvieira@arm.com>2024-10-04 13:43:46 +0100
committerAndre Vieira <andre.simoesdiasvieira@arm.com>2024-10-04 13:46:13 +0100
commit7766a2c1eb683eeee352ce117e8ed014665f392f (patch)
treeff20e324233a150c9cb11f6648c813f25b7cfcb7 /gcc/config
parent16cd00a10035992f52ed67ff77eab20039555b03 (diff)
downloadgcc-7766a2c1eb683eeee352ce117e8ed014665f392f.zip
gcc-7766a2c1eb683eeee352ce117e8ed014665f392f.tar.gz
gcc-7766a2c1eb683eeee352ce117e8ed014665f392f.tar.bz2
arm: Fix missed CE optimization for armv8.1-m.main [PR 116444]
This patch restores missed optimizations for armv8.1-m.main targets that were missed when the generation of csinc, csinv and csneg were enabled for the same with patch series containing: commit c2bb84be4a6e581bbf45891457ee632a07416982 Author: Sudi Das <sudi.das@arm.com> Date: Fri Sep 18 15:47:46 2020 +0100 [PATCH 2/5][Arm] New pattern for CSINV instructions The original patch series makes use of the "noce" machinery to transform RTL into patterns that later match the Armv8.1-M Mainline, by getting the target hook TARGET_HAVE_CONDITIONAL_EXECUTION, to return FALSE for such targets prior to reload_completed. The same machinery however was transforming other RTL patterns which were later on causing the "ce" pass post reload_completed to no longer optimize conditional execution opportunities, which was causing the regression observed in PR target/116444, a regression of 'testsuite/gcc.target/arm/thumb-ifcvt-2.c' when ran for an Armv8.1-M Mainline target. This patch implements the target hook TARGET_NOCE_CONVERSION_PROFITABLE_P to only allow "noce" to generate patterns that match CSINV, CSINC and CSNEG. Thus ensuring that the early "ce" passes do not ruin things for later ones. gcc/ChangeLog: PR target/116444 * config/arm/arm-protos.h (arm_noce_conversion_profitable_p): New declaration. * config/arm/arm.cc (arm_is_v81m_cond_insn): New helper function used in ... (arm_noce_conversion_profitable_p): ... here. New function to implement ... (TARGET_NOCE_PROFITABLE_P): ... this target hook. New define.
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/arm/arm-protos.h1
-rw-r--r--gcc/config/arm/arm.cc87
2 files changed, 88 insertions, 0 deletions
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 50cae2b..b694589 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -210,6 +210,7 @@ extern bool arm_pad_reg_upward (machine_mode, tree, int);
#endif
extern int arm_apply_result_size (void);
extern opt_machine_mode arm_get_mask_mode (machine_mode mode);
+extern bool arm_noce_conversion_profitable_p (rtx_insn *,struct noce_if_info *);
#endif /* RTX_CODE */
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 62eea50..077c80d 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -815,6 +815,9 @@ static const scoped_attribute_specs *const arm_attribute_table[] =
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P arm_modes_tieable_p
+#undef TARGET_NOCE_CONVERSION_PROFITABLE_P
+#define TARGET_NOCE_CONVERSION_PROFITABLE_P arm_noce_conversion_profitable_p
+
#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS arm_can_change_mode_class
@@ -36089,6 +36092,90 @@ arm_get_mask_mode (machine_mode mode)
return default_get_mask_mode (mode);
}
+/* Helper function to determine whether SEQ represents a sequence of
+ instructions representing the Armv8.1-M Mainline conditional arithmetic
+ instructions: csinc, csneg and csinv. The cinc instruction is generated
+ using a different mechanism. */
+
+static bool
+arm_is_v81m_cond_insn (rtx_insn *seq)
+{
+ rtx_insn *curr_insn = seq;
+ rtx set;
+ /* The pattern may start with a simple set with register operands. Skip
+ through any of those. */
+ while (curr_insn)
+ {
+ set = single_set (curr_insn);
+ if (!set
+ || !REG_P (SET_DEST (set)))
+ return false;
+
+ if (!REG_P (SET_SRC (set)))
+ break;
+ curr_insn = NEXT_INSN (curr_insn);
+ }
+
+ if (!set)
+ return false;
+
+ /* The next instruction should be one of:
+ NEG: for csneg,
+ PLUS: for csinc,
+ NOT: for csinv. */
+ if (GET_CODE (SET_SRC (set)) != NEG
+ && GET_CODE (SET_SRC (set)) != PLUS
+ && GET_CODE (SET_SRC (set)) != NOT)
+ return false;
+
+ curr_insn = NEXT_INSN (curr_insn);
+ if (!curr_insn)
+ return false;
+
+ /* The next instruction should be a COMPARE. */
+ set = single_set (curr_insn);
+ if (!set
+ || !REG_P (SET_DEST (set))
+ || GET_CODE (SET_SRC (set)) != COMPARE)
+ return false;
+
+ curr_insn = NEXT_INSN (curr_insn);
+ if (!curr_insn)
+ return false;
+
+ /* And the last instruction should be an IF_THEN_ELSE. */
+ set = single_set (curr_insn);
+ if (!set
+ || !REG_P (SET_DEST (set))
+ || GET_CODE (SET_SRC (set)) != IF_THEN_ELSE)
+ return false;
+
+ return !NEXT_INSN (curr_insn);
+}
+
+/* For Armv8.1-M Mainline we have both conditional execution through IT blocks,
+ as well as conditional arithmetic instructions controlled by
+ TARGET_COND_ARITH. To generate the latter we rely on a special part of the
+ "ce" pass that generates code for targets that don't support conditional
+ execution of general instructions known as "noce". These transformations
+ happen before 'reload_completed'. However, "noce" also triggers for some
+ unwanted patterns [PR 116444] that prevent "ce" optimisations after reload.
+ To make sure we can get both we use the TARGET_NOCE_CONVERSION_PROFITABLE_P
+ hook to only allow "noce" to generate the patterns that are profitable. */
+
+bool
+arm_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info)
+{
+ if (!TARGET_COND_ARITH
+ || reload_completed)
+ return true;
+
+ if (arm_is_v81m_cond_insn (seq))
+ return true;
+
+ return false;
+}
+
/* Output assembly to read the thread pointer from the appropriate TPIDR
register into DEST. If PRED_P also emit the %? that can be used to
output the predication code. */