On Thu, Jun 19, 2025 at 02:14:26PM +0100, Stafford Horne wrote: > When working on PR120587 I found that the ce1 pass was not able to > properly optimize branches on OpenRISC. This is because of the early > splitting of "compare" and "branch" instructions during the expand pass. > > Convert the cbranch* instructions from define_expand to > define_insn_and_split. This dalays the instruction split until after > the ce1 pass is done giving ce1 the best opportunity to perform the > optimizations on the original form of cbranch<mode>4 instructions. > > gcc/ChangeLog: > > * config/or1k/or1k.cc (or1k_noce_conversion_profitable_p): New > function. > (or1k_is_cmov_insn): New function. > (TARGET_NOCE_CONVERSION_PROFITABLE_P): Define macro. > * config/or1k/or1k.md (cbranchsi4): Convert to insn_and_split. > (cbranch<mode>4): Convert to insn_and_split. > > Signed-off-by: Stafford Horne <sho...@gmail.com> > --- > gcc/config/or1k/or1k.cc | 54 +++++++++++++++++++++++++++++++++++++++++ > gcc/config/or1k/or1k.md | 32 ++++++++++++++++++++++-- > 2 files changed, 84 insertions(+), 2 deletions(-) > > diff --git a/gcc/config/or1k/or1k.cc b/gcc/config/or1k/or1k.cc > index f1c92c6bf6c..36c16a51d44 100644 > --- a/gcc/config/or1k/or1k.cc > +++ b/gcc/config/or1k/or1k.cc > @@ -1654,6 +1654,60 @@ or1k_rtx_costs (rtx x, machine_mode mode, int > outer_code, int /* opno */, > #undef TARGET_RTX_COSTS > #define TARGET_RTX_COSTS or1k_rtx_costs > > +static bool > +or1k_is_cmov_insn (rtx_insn *seq) > +{ > + rtx_insn *curr_insn = seq; > + rtx set = NULL_RTX; > + > + /* 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 it's not a simple reg or immediate break. */ > + if (REG_P (SET_SRC (set)) || CONST_INT_P (SET_SRC (set))) > + curr_insn = NEXT_INSN (curr_insn); > + else > + break;
Indentation issue. > + } > + > + /* The next instruction should be a compare. OpenRISC has many operators > used > + for comparison so skip and confirm the next is IF_THEN_ELSE. */ > + curr_insn = NEXT_INSN (curr_insn); Need to check curr_insn before calling NEXT_INSN () to avoid failures. > + 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); > +} > + > +/* Implement TARGET_NOCE_CONVERSION_PROFITABLE_P. We detect if the > conversion > + resulted in a l.cmov instruction and if so we consider it more profitable > than > + branch instructions. */ > + > +static bool > +or1k_noce_conversion_profitable_p (rtx_insn *seq, > + struct noce_if_info *if_info) > +{ > + if (TARGET_CMOV) > + return or1k_is_cmov_insn (seq); > + > + return default_noce_conversion_profitable_p (seq, if_info); > +} > + > +#undef TARGET_NOCE_CONVERSION_PROFITABLE_P > +#define TARGET_NOCE_CONVERSION_PROFITABLE_P or1k_noce_conversion_profitable_p > > /* A subroutine of the atomic operation splitters. Jump to LABEL if > COND is true. Mark the jump as unlikely to be taken. */ > diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md > index a30cc18892d..bf7125375ac 100644 > --- a/gcc/config/or1k/or1k.md > +++ b/gcc/config/or1k/or1k.md > @@ -609,7 +609,7 @@ > ;; Branch instructions > ;; ------------------------------------------------------------------------- > > -(define_expand "cbranchsi4" > +(define_insn_and_split "cbranchsi4" > [(set (pc) > (if_then_else > (match_operator 0 "comparison_operator" > @@ -618,13 +618,27 @@ > (label_ref (match_operand 3 "" "")) > (pc)))] > "" > + "#" > + "&& 1" > + [(const_int 0)] > { > + rtx label; > + > + /* Generate *scc */ > or1k_expand_compare (operands); > + /* Generate *cbranch */ > + label = gen_rtx_LABEL_REF (VOIDmode, operands[3]); > + emit_jump_insn (gen_rtx_SET (pc_rtx, > + gen_rtx_IF_THEN_ELSE (VOIDmode, > + operands[0], > + label, > + pc_rtx))); > + DONE; > }) > > ;; Support FP branching > > -(define_expand "cbranch<F:mode>4" > +(define_insn_and_split "cbranch<F:mode>4" > [(set (pc) > (if_then_else > (match_operator 0 "fp_comparison_operator" > @@ -633,8 +647,22 @@ > (label_ref (match_operand 3 "" "")) > (pc)))] > "TARGET_HARD_FLOAT" > + "#" > + "&& 1" > + [(const_int 0)] > { > + rtx label; > + > + /* Generate *scc */ > or1k_expand_compare (operands); > + /* Generate *cbranch */ > + label = gen_rtx_LABEL_REF (VOIDmode, operands[3]); > + emit_jump_insn (gen_rtx_SET (pc_rtx, > + gen_rtx_IF_THEN_ELSE (VOIDmode, > + operands[0], > + label, > + pc_rtx))); > + DONE; > }) > > (define_insn "*cbranch" > -- > 2.49.0 >