> 2017-11-17 Daniel Cederman <ceder...@gaisler.com> > > * config/sparc/sparc.c (fpop_reg_depend_p): New function. > (div_sqrt_insn_p): New function. > (sparc_do_work_around_errata): Insert NOP instructions to > prevent sequences that could trigger the TN-0013 errata for > certain LEON3 processors. > (pass_work_around_errata::gate): Also test sparc_fix_tn0013. > (sparc_option_override): Set sparc_fix_tn0013 appropriately. > * config/sparc/sparc.md (fix_tn0013): New attribute. > (in_branch_delay): Prevent div and sqrt in delay slot if fix_tn0013. > * config/sparc/sparc.opt (sparc_fix_tn0013: New variable.
OK for mainline and 7 branch modulo the following nits: > +/* True if any of the floating-point instruction's source > + registers is the same as the provided register. */ > + > +static int > fpop_reg_depend_p (rtx_insn *insn, unsigned int reg) 'bool' instead of 'int'. "True if any of INSN's source register(s) is REG". The function's name is awkward. insn_uses_reg_p? insn_reads_reg_p? > +/* True if the instruction is floating-point division or > + floating-point square-root. */ > + > +static int > +div_sqrt_insn_p (rtx_insn *insn) 'bool' instead of 'int'. "True if INSN is a floating-point ..." > + if ( GET_CODE (PATTERN (insn)) != SET) > + return false; No space before GET_CODE. > @@ -1064,6 +1097,80 @@ sparc_do_work_around_errata (void) > insert_nop = true; > } > > + /* Look for sequences that could trigger the TN-0013 errata. */ > + if (sparc_fix_tn0013 > + && NONJUMP_INSN_P (insn) > + && div_sqrt_insn_p (insn)) > + { > + int i; > + int fp_found = 0; > + unsigned int dest_reg; > + rtx_insn *after; > + > + dest_reg = REGNO (SET_DEST (single_set (insn))); const unsigned int dest_reg = REGNO (SET_DEST (single_set (insn))); > + next = next_active_insn (insn); > + if (!next) > + break; > + > + for (after = next, i = 0; i < 4; i++) > + { > + /* Count floating-point operations. */ > + if (i != 3 > + && fpop_insn_p (after)) On a single line. > + /* If the insn uses the destination register of > + the div/sqrt, then it cannot be problematic. */ > + if (fpop_reg_depend_p (after, dest_reg)) > + break; > + fp_found++; > + } > + > + /* Count floating-point loads. */ > + if (i != 3 > + && (set = single_set (after)) != NULL_RTX > + && REG_P (SET_DEST (set)) > + && REGNO (SET_DEST (set)) > 31) > + { > + /* If the insn uses the destination register of > + the div/sqrt, then it cannot be problematic. */ > + if (REGNO (SET_DEST (set)) == dest_reg) > + break; > + fp_found++; > + } > + > + /* Check if this is a problematic sequence. */ > + if (i > 1 > + && fp_found >= 2 > + && div_sqrt_insn_p (after)) > + { > + /* Add extra NOP to prevent second version of > + problematic sequence. */ > + if (i == 2) > + emit_insn_before (gen_nop (), next); > + insert_nop = true; > + break; > + } So you emit 2 NOPs in a row if i == 2? > diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt > index 22267f5..43cd964 100644 > --- a/gcc/config/sparc/sparc.opt > +++ b/gcc/config/sparc/sparc.opt > @@ -253,6 +253,10 @@ Enable workarounds for the errata of the GR712RC > processor. TargetVariable > unsigned int sparc_fix_b2bst > > +;; Enable workaround for TN-0013 errata > +TargetVariable > +unsigned int sparc_fix_tn0013 Can we find a more evocative name for the variable? -- Eric Botcazou